在 Circe 中使用不同数据类型处理 json
Process json with different data type in Circe
在我的例子中,相同的 json 字段可能有不同的数据类型。示例:
"need_exp":1500
或
"need_exp":"-"
如何处理这个案例?我知道它可以由 parse
处理或使用自定义编码器,但这是一个非常复杂的 json 文本,有没有办法解决这个问题而不重写整个解码器(例如,只是 "tell" 解码器将 need_exp
字段中的所有 Int
转换为 String
)?
它被称为析取,可以用 Scala 标准编码 Either
class。
只需将 json 映射到以下 class:
case class Foo(need_exp: Either[String, Int])
我的解决方案是使用自定义解码器。改写一小部分JSON就可以了
例如有一个简单的JSON:
{
/*many fields*/
"hotList":[/* ... many lists inside*/],
"list":[ {/*... many fields*/
"level_info":{
"current_exp":11463,
"current_level":5,
"current_min":10800,
"next_exp":28800 //there is the problem
},
"sex":"\u4fdd\u5bc6"},/*...many lists*/]
}
在这种情况下,我不需要重写整个JSON编码器,只需编写一个level_info
的自定义编码器:
implicit val decodeUserLevel: Decoder[UserLevel] = (c: HCursor) => for
{
current_exp <- c.downField("current_exp").as[Int]
current_level <- c.downField("current_level").as[Int]
current_min <- c.downField("current_min").as[Int]
next_exp <- c.downField("next_exp").withFocus(_.mapString
{
case """-""" => "-1"
case default => default
}).as[Int]
} yield
{
UserLevel(current_exp, current_level, current_min, next_exp)
}
它奏效了。
在我的例子中,相同的 json 字段可能有不同的数据类型。示例:
"need_exp":1500
或
"need_exp":"-"
如何处理这个案例?我知道它可以由 parse
处理或使用自定义编码器,但这是一个非常复杂的 json 文本,有没有办法解决这个问题而不重写整个解码器(例如,只是 "tell" 解码器将 need_exp
字段中的所有 Int
转换为 String
)?
它被称为析取,可以用 Scala 标准编码 Either
class。
只需将 json 映射到以下 class:
case class Foo(need_exp: Either[String, Int])
我的解决方案是使用自定义解码器。改写一小部分JSON就可以了
例如有一个简单的JSON:
{
/*many fields*/
"hotList":[/* ... many lists inside*/],
"list":[ {/*... many fields*/
"level_info":{
"current_exp":11463,
"current_level":5,
"current_min":10800,
"next_exp":28800 //there is the problem
},
"sex":"\u4fdd\u5bc6"},/*...many lists*/]
}
在这种情况下,我不需要重写整个JSON编码器,只需编写一个level_info
的自定义编码器:
implicit val decodeUserLevel: Decoder[UserLevel] = (c: HCursor) => for
{
current_exp <- c.downField("current_exp").as[Int]
current_level <- c.downField("current_level").as[Int]
current_min <- c.downField("current_min").as[Int]
next_exp <- c.downField("next_exp").withFocus(_.mapString
{
case """-""" => "-1"
case default => default
}).as[Int]
} yield
{
UserLevel(current_exp, current_level, current_min, next_exp)
}
它奏效了。