如何将包含不同数据类型属性的 JSON 解析为 Scala 中的泛型类?



我有一个来自 API 响应的 json,如下所示:

[{
value: true(Boolean),
name: "xyz",
date: 11/12/2020
},
{
value: "abc"(String),
name: "djd",
date: 11/12/2020
}]

它基本上具有类似的结构,但其中一个属性(值)可能包含不同的数据类型。如何将此响应解析为类?我正在尝试这样做,但我不确定如何编写 MainData 类。 有什么想法吗?

trait Data[A] {
val value: A
val date: ZonedDateTime
val name: String
}    
case class ClassA(
value: Boolean,
name: String,
date: ZonedDateTime
) extends Data[Boolean]

case class ClassB(
value: String,
name: String,
date: ZonedDateTime
) extends Data[String]
case class MainData(data: Seq[Data[A])

在响应处理程序中,如下所示:

case rsp if 200 == rsp.status =>
val response = rsp.body.as[MainData[A]]

您可以为ClassAClassB创建单独的Reads实例,然后根据value字段的类型使用适当的实例。大致如下:

val aReads = Json.reads[ClassA]
val bReads = Json.reads[ClassB]
implicit val dataReads = new Reads[Data[_]] {
def reads(json: JsValue) = (json  "value") match {
case JsDefined(JsString(_)) => bReads.reads(json)
case JsDefined(JsBoolean(_)) => aReads.reads(json)
case x => JsError(s"Unknown data type: $x")
}
}

这样,您的json.as[Data[_]]json.as[MainData]将拾取dataReads进而调用正确的实例。 或者,您根本不需要使用单独的aReadsbReads读取器,并完全实现read(...)方法:

implicit val dataReads = new Reads[Data[_]] {
def reads(json: JsValue) = {
val name = (json  "name").as[String]
val date = (json  "date").as[ZonedDateTime]
(json  "value") match {
case JsDefined(JsString(str)) => JsSuccess(ClassB(str, name, date))
case JsDefined(JsBoolean(bln)) => JsSuccess(ClassA(bln, name, date))
case x => JsError(s"Unknown data type: $x")
}
}
}

最新更新