scala Spray-json 反序列化嵌套对象
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/21691525/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Spray-json deserializing nested object
提问by user3103600
How to deserialize nested objects correctly in 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
On a side-note, how to spray-json help serializing to a map of fields (with nested map for nested objects)?
附带说明一下,如何使用 Spray-json 帮助序列化到字段映射(嵌套对象的嵌套映射)?
回答by Dave Swartz
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-jsonfor version 1.2.5.
下面的示例演示了 JSON -> 抽象语法树 -> Scala 案例类,并返回自定义字段名称和对可选案例类成员的支持。该示例源自https://github.com/spray/spray-json 上的 1.2.5 版的 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])
}
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)
回答by akauppi
To your remaining question - how to reuse JSON conversions within a wrapping type:
对于您剩下的问题 - 如何在包装类型中重用 JSON 转换:
"person-field" -> JsObject("p-name" -> JsString(c.p.name))
I would change this to:
我会将其更改为:
"person-field" -> p.toJson
This way, you are letting the Personcase class JSONify itself, instead of introducing another way in the wrapping object. DRYand simpler.
这样,您Person就让案例类 JSONify 本身,而不是在包装对象中引入另一种方式。干燥和简单。
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:
使用.convertTo[Person]这里:
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.
如果有问题,请寻求更多帮助。我在自己的项目中有类似的结构,但没有尝试在这种情况下运行它们。

