2014-02-11 130 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]) 

如果有問題,請向更多的幫助。我在自己的項目中有類似的結構,但沒有嘗試在這種情況下運行它們。

相關問題