繁体   English   中英

在scala中播放json:使用未知字段反序列化json而不会丢失它们

[英]play json in scala: deserializing json with unknown fields without losing them

考虑我有一个JSON如下:

 {
  "a": "aa",
  "b": "bb",
  "c": "cc",
  "d": "dd", // unknown in advance
  "e": { //unknown in advance
    "aa": "aa"
  }
}

我确定json将包含a,b,c,但我不知道此json可能包含哪些其他字段。

我想将此JSON序列化为包含a,b,c的case类,但另一方面不要丢失其他字段(将它们保存在地图中,以便该类将反序列化为与接收的相同的json)。

想法?

您可以为此使用自定义Reads ,例如:

import play.api.libs.json._
import play.api.libs.functional.syntax._

case class MyData(a: String, b: String, c:String, other: Map[String, JsValue])

object MyData {
  val abcReader: Reads[(String, String, String)] = (
    (JsPath \ "a").read[String] and
    (JsPath \ "b").read[String] and
    (JsPath \ "c").read[String]
  ).tupled

  implicit val reader: Reads[MyData] = Reads { json =>
    abcReader.reads(json).map {
      case (a, b, c) =>
        val other = json.as[JsObject].value -- Seq("a", "b", "c")
        MyData(a, b, c, other.toMap)
    }
  }
}

一种选择是捕获Map[String,JsValue]的“未知”字段,以后可以根据需要从中提取值。

case class MyClass(a: String, b: String, c: String, extra: Map[String, JsValue])
implicit val reads: Reads[MyClass] = (
  (__ \ "a").read[String] and
  (__ \ "b").read[String] and
  (__ \ "c").read[String] and
  __.read[Map[String, JsValue]]
    .map(_.filterKeys(k => !Seq("a", "b", "c").contains(k)))
)(MyClass.apply _)

// Result:
// MyClass(aa,bb,cc,Map(e -> {"aa":"aa"}, d -> "dd"))

同样,您可以执行WritesFormat这样的操作:

// And a writes...
implicit val writes: Writes[MyClass] = (
  (__ \ "a").write[String] and
  (__ \ "b").write[String] and
  (__ \ "c").write[String] and
  __.write[Map[String, JsValue]]
)(unlift(MyClass.unapply _))

// Or combine the two...
implicit val format: Format[MyClass] = (
  (__ \ "a").format[String] and
  (__ \ "b").format[String] and
  (__ \ "c").format[String] and
  __.format[Map[String, JsValue]](Reads
    .map[JsValue].map(_.filterKeys(k => !Seq("a", "b", "c").contains(k))))
)(MyClass.apply, unlift(MyClass.unapply))

注意:这看起来有些混乱,因为您为Map[String,JsValue]format提供了一个显式的Reads作为参数( Reads.map ),然后对其进行了转换(使用.map 方法 )以删除已捕获的值。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM