将对象的json数组解析为相应的case类

将对象的json数组解析为相应的case类,json,scala,playframework,Json,Scala,Playframework,我有一个json设置数组,如下所示: 我想将其解析为设置对象的序列。我尝试使用trait定义json格式,并根据json对象中的数据类型定义不同的case类: sealed trait Setting case class StringSetting(name: String, key: String, default: String) extends Setting case class IntSetting(name: String, key: String, default: Int) e

我有一个json设置数组,如下所示:

我想将其解析为
设置
对象的
序列
。我尝试使用trait定义json格式,并根据json对象中的数据类型定义不同的case类:

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]

是否有方法将每个设置映射到相应的案例类

  • 简单的方法是提供Reads[Setting](如果您的目标只是将json转换为object),以便json反序列化程序能够构建正确的设置变量

    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)
    
  • 但是,如果在不同的子类中具有相同的“default”类型,则这将不起作用。在这种情况下,JSON反序列化程序无法区分 在这两个案例类之间

  • 另一种方法是使用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 variant library的更多信息

    可能重复的请看我的代码,这是一个非常好的答案,很好的引用,并且对主题有了清晰的理解。原来的海报是如此接近;看到亲吻原则在这个网站上的应用让人耳目一新。
    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] 
    }