我正在尝试将格式为“ 5m”,“ 5s”或“ 5ms”的字符串解码为FiniteDuration类型的对象,这些对象分别为5分钟,5秒,5毫秒。
我正在尝试为涉及FiniteDuration类的项目创建自定义解码器和编码器。编码器没问题,因为它只是读取FiniteDuration类的字段并生成一个字符串。但是,我在编写解码器时遇到困难,并且想知道我所做的事情是否完全可能。
FiniteDuration是一个具有如下构造函数的类:FiniteDuration(length:Long,unit:TimeUnit)。 Scala附带了一些方便的语法糖,因此可以使用5分钟,5秒或5毫秒表示法来调用该类。在这种情况下,Scala会为您创建FiniteDuration类。
这个想法是将FiniteDuration类转换为字符串,例如“ 5m”,“ 5s”或“ 5ms”,这样在眼睛上就更容易了。
implicit val d2json: Encoder[FiniteDuration] = new Encoder[FiniteDuration] {
override def apply(a: FiniteDuration): Json = ???
}
implicit val json2d: Decoder[FiniteDuration] = new Decoder[FiniteDuration] {
override def apply(c: HCursor): Decoder.Result[FiniteDuration] = ???
}
编码器我应该没有问题。解码器比较棘手。我不确定该怎么做,因为apply方法需要输入HCursor类型。
答案 0 :(得分:2)
我想您希望您的解析器符合HOCON标准吗?
然后,您可以重复使用或复制com.typesafe.config
库中使用的解析器。您需要的方法是
public static long parseDuration(String input,
ConfigOrigin originForException, String pathForException)
答案 1 :(得分:2)
这是一个有效的基本实现(可能需要根据您对FiniteDuration的编码方式进行调整。
基本上,您需要做的是将光标的值设为String
,将字符串分成持续时间和句点,然后尝试将这两个部分都转换为Long
和{{1} }(因为TimeUnit
构造函数接受它们作为参数)。
请注意,这些转换必须返回FiniteDuration
才能与Either[DecodingFailure, _]
的返回类型保持一致,因此您可以在理解中使用它们。
我对这些转换使用了隐式扩展方法,因为我发现它们很方便,但是您可以编写基本功能。
cursor.as[_]
答案 2 :(得分:0)
我认为解码 CREATE TABLE user_to_sub_user (
user_id int,
sub_user_id int
);
的更好方法是使用现有的类 FiniteDuration
并且它是从 std lib 解析的:
scala.concurrent.Duration
我从 import io.circe.parser.decode
import io.circe.{ CursorOp, Decoder, DecodingFailure, HCursor }
import cats.syntax.validated._
import cats.data.Validated
import scala.concurrent.duration.{ Duration, FiniteDuration }
import scala.language.postfixOps
import scala.util.Try
import scala.concurrent.duration._
def parseDuration(ops: => List[CursorOp])
(d: String): Either[DecodingFailure, FiniteDuration] =
Validated
.fromTry(Try(Duration(d)))
.andThen {
case _: Duration.Infinite => new Exception("Field can not be infinite")
.invalid[FiniteDuration]
case duration: FiniteDuration => duration.valid[Throwable]
}
.leftMap(DecodingFailure.fromThrowable(_, ops))
.toEither
implicit val fDurationDecoder: Decoder[FiniteDuration] = (c: HCursor) =>
c.as[String].flatMap(parseDuration(c.history))
添加了 Validated
只是为了更舒适的错误处理并添加对无限输入的验证
cats