【问题标题】:Parse a json array of object to their appropriate case class将对象的 json 数组解析为相应的案例类
【发布时间】:2016-09-21 09:32:13
【问题描述】:

我有一个 settings 的 json 数组,如下所示:

[
  {
    "name": "Company Name",
    "key": "company_name",
    "default": "Foo"
  }, {
    "name": "Deposit Weeks",
    "key": "deposit_weeks",
    "default": 6
  }, {
    "name": "Is VAT registered",
    "key": "vat_registered",
    "default": false
  }
]

我想将其解析为 SeqSetting 对象。我试图通过使用特征并根据 json 对象中的数据类型定义不同的案例类来定义我的 json 格式:

sealed trait Setting
case class StringSetting(name: String, key: String, default: String) extends Setting
case class IntSetting(name: String, key: String, default: Int) extends Setting
case class BoolSetting(name: String, key: String, default: Boolean) extends Setting

现在我尝试解析 json:

val json = Json.parse(jsonStr)
implicit val jsonFormat: Format[Setting] = Json.format[Setting]

val result = Try(json.as[Seq[Setting]])

这里出现编译错误:

错误:(19, 61) 未找到 unapply 或 unapplySeq 函数 隐式 val jsonFormat: Format[Setting] = Json.format[Setting]

有没有办法将每个设置映射到相应的案例类?

【问题讨论】:

标签: json scala playframework


【解决方案1】:
  1. 天真的方法是提供 Reads[Setting](如果您的目标只是将 json 转换为对象),以便 JSON 反序列化器能够构建正确的 Setting 变体。

    import play.api.libs.json._
    import play.api.libs.functional.syntax._
    
    implicit val settingReads: Reads[Setting] = (__ \ "default").read[String].map[Setting](StringSetting) |
                                        (__ \ "default").read[Int].map[Setting](IntSetting) |
                                        (__ \ "default").read[Boolean].map[Setting](BoolSetting)
    

但是,如果您在不同的子类中具有相同的“默认”类型,这将不起作用。在这种情况下 JSON 反序列化器无法区分 在这两个案例类之间。

  1. 另一种方法是使用 play json 变体库。

    import julienrf.variants.Variants
    
    sealed trait Setting
    case class StringSetting(name: String, key: String, default: String) extends Setting
    case class IntSetting(name: String, key: String, default: Int) extends Setting
    case class BoolSetting(name: String, key: String, default: Boolean) extends Setting
    
    object Setting {
      implicit val format: Format[Setting] = Variants.format[Setting] 
    }
    

    Variant.format 为设置提供读取和写入。确保在声明所有可能的子类之后分配“隐式 val 格式”。

更多关于play json变体库的信息click here

【讨论】:

  • 这是一个很好的答案,很好的引用和对主题的清晰理解。原始海报如此接近;看到在这个网站上应用的 KISS 原则令人耳目一新。
猜你喜欢
  • 2019-01-18
  • 1970-01-01
  • 1970-01-01
  • 2021-09-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-22
相关资源
最近更新 更多