Spray-json反序列化嵌套对象

Posted

技术标签:

【中文标题】Spray-json反序列化嵌套对象【英文标题】:Spray-json deserializing nested object 【发布时间】:2014-03-08 15:06:25 【问题描述】:

如何在 spray-json 中正确反序列化嵌套对象?

    import spray.json._

    case class Person(name: String)

    case class Color(n: String, r: Int, g: Int, b: Int, p: Person)

    object MyJsonProtocol extends DefaultJsonProtocol 

      implicit object ColorJsonFormat extends RootJsonFormat[Color] 
        def write(c: Color) = JsObject(
          "color-name" -> JsString(c.n),
          "Green" -> JsNumber(c.g),
          "Red" -> JsNumber(c.r),
          "Blue" -> JsNumber(c.b),
          "person-field" -> JsObject("p-name" -> JsString(c.p.name))
        )

        def read(value: JsValue) = 
          value.asJsObject.getFields("color-name", "Red", "Green", "Blue", "person-field") match 
            case Seq(JsString(name), JsNumber(red), JsNumber(green), JsNumber(blue), JsObject(person)) =>
              Color(name, red.toInt, green.toInt, blue.toInt, null) //gotta replace null with correct deserializer
            case _ => throw new DeserializationException("Color expected")
          
        
      

    

    import MyJsonProtocol._

    val jsValue = Color("CadetBlue", 95, 158, 160, Person("guest")).toJson

    jsValue.prettyPrint

    val color = jsValue.convertTo[Color] //person is missing of course

在旁注中,如何将 spray-json 帮助序列化为字段映射(嵌套对象的嵌套映射)?

【问题讨论】:

【参考方案1】:

下面的示例演示了 JSON -> 抽象语法树 -> Scala 案例类,并返回自定义字段名称和对可选案例类成员的支持。该示例源自 https://github.com/spray/spray-json 的 spray-json 文档,适用于版本 1.2.5。

package rando

import spray.json._

case class Color(name: String, red: Int, green: Int, blue: Int)

case class Team(name: String, color: Option[Color])

object MyJsonProtocol extends DefaultJsonProtocol 
  implicit val colorFormat = jsonFormat(Color, "name", "r", "g", "b")
  implicit val teamFormat = jsonFormat(Team, "name", "jersey")

import MyJsonProtocol._

object GoSox extends App 
  val obj = Team("Red Sox", Some(Color("Red", 255, 0, 0)))
  val ast = obj.toJson
  println(obj)
  println(ast.prettyPrint)
  println(ast.convertTo[Team])
  println(""" "name": "Red Sox", "jersey": null """.asJson.convertTo[Team])
  println(""" "name": "Red Sox" """.asJson.convertTo[Team])

该示例在执行时输出以下内容:

Team(Red Sox,Some(Color(Red,255,0,0)))

  "name": "Red Sox",
  "jersey": 
    "name": "Red",
    "r": 255,
    "g": 0,
    "b": 0
  

Team(Red Sox,Some(Color(Red,255,0,0)))
Team(Red Sox,None)
Team(Red Sox,None)

【讨论】:

Option[Color]怎么样?所以 Team 类变成了 case class Team(name: String, color: Option[Color]) 你能告诉我你已经尝试过什么吗? Spray-json 文档有用吗? 我想在序列化过程中自定义字段名称。 我以为您只是在玩弄这段代码来理解 spray-json,您的问题“如何在 spray-json 中正确反序列化嵌套对象?”进一步强化了这一点。我建议您将来使用更具体的问题。例如,“我有以下类。代码无法编译并产生以下错误......为了清楚起见,我需要处理空值并希望使用自定义字段名称进行序列化/反序列化。”我现在将使用自定义字段名称和 null 处理来更新答案。我所做的只是阅读文档仅供参考。 那里的文档真的没有帮助。特别适合 Scala 新手。无论如何,我会尝试这个 sn-p 并将其标记为已接受。谢谢【参考方案2】:

关于您剩下的问题 - 如何在包装类型中重用 JSON 转换:

"person-field" -> JsObject("p-name" -> JsString(c.p.name))

我会将其更改为:

"person-field" -> p.toJson

这样,您让Person 案例类 JSONify 自身,而不是在包装对象中引入另一种方式。 DRY 更简单。

还有:

case Seq(JsString(name), JsNumber(red), JsNumber(green), JsNumber(blue), JsObject(person)) => 
  Color(name, red.toInt, green.toInt, blue.toInt, null)

在此处使用.convertTo[Person]

case Seq(JsString(name), JsNumber(red), JsNumber(green), JsNumber(blue), jsv) => 
  Color(name, red.toInt, green.toInt, blue.toInt, jsv.convertTo[Person])

如果有问题,请寻求更多帮助。我在自己的项目中有类似的结构,但没有尝试在这种情况下运行它们。

【讨论】:

【参考方案3】:
import models.Address, Patient
import spray.json._

object Hospital 

  object MyJsonProtocol extends DefaultJsonProtocol 
    implicit val address = jsonFormat(Address, "country", "state", "zip")
    implicit val patient = jsonFormat(Patient, "name", "regNumber", "address")
  

  import MyJsonProtocol._

  def main(args: Array[String]): Unit = 
    val p1 = Patient(name = "Amar", regNumber = 234, address = Address("IN", "KA", 49))
    println(p1.toJson.sortedPrint)
  


输出


  "address": 
    "country": "IN",
    "state": "KA",
    "zip": 49
  ,
  "name": "Amar",
  "regNumber": 234

【讨论】:

以上是关于Spray-json反序列化嵌套对象的主要内容,如果未能解决你的问题,请参考以下文章

Json.NET:反序列化嵌套字典

使用 RestTemplate 反序列化嵌套对象

JSON.net 反序列化对象嵌套数据

将JSON对象反序列化为嵌套的C#对象

Java - 如何反序列化带有嵌套对象和列表的 JSON 数组? [复制]

反序列化嵌套的 json 对象。当内部对象可能不同时