Spray-json deserializing nested object

前端 未结 2 1116
名媛妹妹
名媛妹妹 2020-12-28 23:03

How to deserialize nested objects correctly in spray-json?

    import spray.json._

    case class Person(name: String)

    case class Color(n: String, r: I         


        
相关标签:
2条回答
  • 2020-12-28 23:33

    The example below demonstrates JSON -> Abstract Syntax Tree -> Scala Case Classes and back with custom field names and support for optional case class members. The example is derived from the spray-json documentation at https://github.com/spray/spray-json for version 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])
    }
    

    The example outputs the following when executed:

    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)
    
    0 讨论(0)
  • 2020-12-28 23:42

    To your remaining question - how to reuse JSON conversions within a wrapping type:

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

    I would change this to:

    "person-field" -> p.toJson
    

    This way, you are letting the Person case class JSONify itself, instead of introducing another way in the wrapping object. DRY and simpler.

    And:

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

    Use the .convertTo[Person] here:

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

    If there are problems, please ask for more help. I have similar structure in my own project but didn't try to run them in this context.

    0 讨论(0)
提交回复
热议问题