json - 在 circe 中解码 case 类、String 或 Int
问题描述
我使用一些带有 json 响应的 Rest API,其中包含一种“混合”字段。混合是指它可以采用不同类型的值。在我的情况下Object
,String
并且Int
是允许的。Object
本身由 1和Int
1组成String
。
我需要解码的对象如下所示:
我
{
field1: 32,
...
value: {
id: 23,
text: "text"
}
}
二
{
field1: 32,
...
value: 21
}
三
{
field1: 32,
...
value: "value"
}
如何处理circe中的此类对象?
解决方案
假设您的案例类是:
@JsonCodec(decodeOnly = true)
case class X(id: Int, text: String)
然后我可以假设您的字段类型为:
type Mixed = X Either Int Either String
解码可能如下所示:
implicit val mixedDecoder: Decoder[Mixed] =
Decoder[X].map[Mixed](x => Left(Left(x))) or Decoder[Int].map[Mixed](i => Left(Right(i))) or Decoder[String].map[Mixed](s => Right(s))
如果您定义它们的组合方式,您可以派生编解码器Either
:左胜、右胜或任何您喜欢的:
implicit def eitherDecode[L: Decoder, R: Decoder]: Decoder[L Either R] =
Decoder[L].map[L Either R](Left(_)) or Decoder[R].map[L Either R](Right(_))
或者,您可以创建自己的 ADT(密封特征 + 案例类),然后编写手写解码器以避免使用鉴别器字段。
底线是你必须以某种方式表达你正在解码的类型的多态性(以一种理智的方式 -Any
不算数),然后提供一个解码器来解码它。然后你可以简单地使用它:
@JsonCodec(decodeOnly = true)
case class BigClass(field1: String, value: Mixed)
推荐阅读
- ios - 如何让 CoreData 的这种实现在我的框架中工作?
- go - 具有多个输入的 ParDo 函数
- laravel - 每次我从请求或 Auth 门面获取用户时,Laravel Passport 都会调用 oauth_access_tokens
- r - 为什么 Rstudio 中的方法不同?
- android - 如何仅在特定的线性布局上通过水平滑动打开抽屉?
- javascript - 后代选择器忽略样式 - JSS
- arrays - 无法从 BAT 文件中的数组中获取值
- csv - 如何从 pyarrow 中的时间戳获取“年”“月”“日期”?
- c - 未知类型名称 size_t
- c# - C# 库 Binance.NET:获取当前的平均硬币价格