2014-02-11 126 views
9

如何在spray-json中正确反序列化嵌套对象?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 

在一个侧面说明,如何喷雾JSON序列化的帮助,以地图的田块(嵌套地图嵌套对象)?

回答

15

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

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) 
+0

选项[颜色]怎么样?所以团队成为 案例类团队(名称:字符串,颜色:选项[颜色]) – user3103600

+0

你能告诉我你已经试过了吗? spray-json文档有帮助吗? –

+0

我想在序列化期间自定义字段名称。 – user3103600

1

要在剩下的问题 - 如何在包装类型中重复使用JSON转换:

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

我将其更改为:

"person-field" -> p.toJson 

这样,您就让Person case class 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]) 

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

相关问题