【问题标题】:How to parse JSON containing a property with different data types into a generic class in Scala?如何将包含具有不同数据类型的属性的 JSON 解析为 Scala 中的泛型类?
【发布时间】:2021-03-06 01:32:28
【问题描述】:

我有一个来自 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]]

【问题讨论】:

  • 您使用的是哪个 JSON 库?
  • 我正在使用 play.api.libs.json

标签: json scala rest generics playframework


【解决方案1】:

您可以为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,而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")
    }
  }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-05
    • 2022-11-02
    • 1970-01-01
    • 2015-07-09
    • 2020-03-27
    相关资源
    最近更新 更多