2012-12-16 60 views
1

我使用內置的jerson與playframework 2,和所有我想要的是序列化映射,包含不同類型的值:Jerkson。序列化映射到JsValue

object AppWriter extends Writes[Application] { 
    def writes(app: Application): JsValue = { 
     Json.toJson(Map(
      "id" -> app.getId.toString, 
      "name" -> app.getName, 
      "users" -> Seq(1, 2, 3) 
     )) 
    } 
} 

在這種情況下,我有:

No Json deserializer found for type scala.collection.immutable.Map[java.lang.String,java.lang.Object]. 
Try to implement an implicit Writes or Format for this type 

通過框架代碼Navigatin顯示有地圖[字符串,V]類型的序列化程序隱式def mapWrites [V] ..,但我不明白爲什麼它不適用。

任何人都可以幫助我嗎?

UPD:我找到簡單的解決方法:

object AppWriter extends Writes[Application] { 
def writes(app: Application): JsValue = { 
    Json.toJson(Map[String, JsValue](
     "id" -> JsNumber(BigDecimal(app.getId)), 
     "name" -> JsString(app.getName), 
     "users" -> JsArray(Seq(1, 2, 3).map(x => JsNumber(x))) 
    )) 
} 

}

,但事實並非如此優雅...

+0

你爲什麼要在這樣的地圖中存儲數據?地圖通常是一個關鍵值存儲區,其中所有值的類型都是相同的。您應該只使用一個案例類來爲這些數據建模。 –

+0

@ DominicBou-Samra,想法聽起來不錯,但看起來像沒有從case class,string only生成JsValue的方法。 –

回答

1

標準的方式做,這是通過創建從JsObject這些字段的各個鍵值對,而不是將這些對放入地圖中。例如,假設您的Application看起來是這樣的:

case class Application(getId: Int, getName: String) 

你可以寫:

import play.api.libs.json._, Json.toJson 

implicit object AppWriter extends Writes[Application] { 
    def writes(app: Application): JsValue = JsObject(
    Seq(
     "id" -> JsNumber(app.getId), 
     "name" -> JsString(app.getName), 
     "users" -> toJson(Seq(1, 2, 3)) 
    ) 
) 
} 

然後:

scala> toJson(Application(1, "test")) 
res1: play.api.libs.json.JsValue = {"id":1,"name":"test","users":[1,2,3]} 

請注意,您不必拼出如何序列化Seq[Int] - 默認的Format實例將爲您完成工作。

+1

非常感謝。但是有沒有這樣的工作流記錄的地方? –

+0

[高級文檔](http://www.playframework.org/documentation/2.0/ScalaJson)目前在編寫自己的'Format'等實例方面非常薄弱。你最好的選擇可能是[API文檔](http://www.playframework.org/documentation/api/2.0/scala/play/api/libs/json/package.html)和第三方教程(以及Stack Overflow , 當然)。 –

+0

我已經試圖挖掘資源,但是我的一週scala知識對於理解整個機制來說太差了,所以play的文檔甚至jerkson都是每個新手都需要的。 –