Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/json/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Json Circe解码器-如果失败,则返回到另一个解码器_Json_Scala_Circe - Fatal编程技术网

Json Circe解码器-如果失败,则返回到另一个解码器

Json Circe解码器-如果失败,则返回到另一个解码器,json,scala,circe,Json,Scala,Circe,我使用Circe进行json操作。我添加了自定义编码器和解码器来处理一些类型,比如Joda Time 在分析DateTime时,我想允许传递多种格式。 例如,dd-MM-yyyy'T'HH:MM:ss'Z'和dd-MM-yyyy'T'HH:MM:ss.SSS'Z' 我对解码器的定义如下: val dateTimeFormat = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss'Z'") val dateTimeFormatWithMillis =

我使用Circe进行json操作。我添加了自定义编码器和解码器来处理一些类型,比如Joda Time

在分析DateTime时,我想允许传递多种格式。 例如,
dd-MM-yyyy'T'HH:MM:ss'Z'
dd-MM-yyyy'T'HH:MM:ss.SSS'Z'

我对解码器的定义如下:

val dateTimeFormat = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss'Z'")
val dateTimeFormatWithMillis = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
implicit val jodaDateTimeFormat: Encoder[DateTime] with Decoder[DateTime] = new Encoder[DateTime] with Decoder[DateTime] {
    override def apply(a: DateTime): Json = Encoder.encodeString(a.toString("yyyy-MM-dd'T'HH:mm:ss'Z'"))

    override def apply(c: HCursor): Result[DateTime] = Decoder.decodeString.map { x =>
      DateTime.parse(x, dateTimeFormat)
    }.apply(c)
  }
现在,如果我输入了一个与
dateTimeFormat
匹配的datetime字符串,那么解码将起作用,但是如果我在
datetimeformatwillis
中传递datetime,它将无法处理

我知道我可以使用
DateTimeFormatterBuilder
添加多个解析器并对其进行处理,但是,我想知道在Circe中是否有一种方法可以链接多个解码器,一个接一个地尝试,直到成功或到达链的末端

您可以使用组合解码器,以便在第一个解码器失败时尝试第二个解码器

以下是一个工作示例:

import org.joda.time.DateTime
导入org.joda.time.format.{DateTimeFormat,DateTimeFormatter}
导入io.circe.{解码器,编码器}
导入io.circe.parser.decode
导入scala.util.Try
val dateTimeFormat=dateTimeFormat.forPattern(“yyyy-MM-dd'T'HH:MM:ss'Z'))
val datetimeformatwillis=DateTimeFormat.forPattern(“yyyy-MM-dd'T'HH:MM:ss.SSS'Z'))
/**创建使用提供的格式解码[[DateTime]]的解码器*/
def dateTimeFormatDecoder(格式:DateTimeFormatter):解码器[日期时间]=
解码器[String].emapTry(str=>Try(DateTime.parse(str,format)))
/**[[Decoder]]用于第一种格式(不含毫秒)*/
val DateTime不带毫秒编码器:解码器[日期时间]=
dateTimeFormatDecoder(dateTimeFormat)
/**[[Decoder]]用于第二种格式(毫秒)*/
val dateTimeWithMillisDecoder:解码器[日期时间]=
dateTimeFormatDecoder(dateTimeFormatWithMillis)
/**使用`Encoder[String].contramap(…)``对[[DateTime]]进行编码,这是
*也许是一个更为惯用的版本
*`Encoder.encodeString(a.toString(“yyyy-MM-dd'T'HH:MM:ss'Z'))`*/
隐式val-jodatetimeencoder:Encoder[DateTime]=
编码器[String].contramap(u.toString(“yyyy-MM-dd'T'HH:MM:ss'Z'))
隐式val jodaDateTimeDecoder:解码器[日期时间]=
不带毫秒编码器的日期时间或带毫秒编码器的日期时间
println(解码[日期时间](“”“2001-02-03T04:05:06Z”)
println(解码[日期时间](“”“2001-02-03T04:05:06.789Z”))
请注意,
编码器
解码器
是分开的,因为
解码器#或
返回一个
解码器
,它不能与组合类一起工作(即
编码器[DateTime]和解码器[DateTime]

另外,
DateTime.parse
调用已用包装,因为
组合器(以及通常所有
解码器
组合器)希望处理
值,而不是异常