杰克森.将映射序列化为 JsValue



我在playframework 2中使用内置的jerson,我想要的只是序列化map,包含不同类型的值:

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

通过框架代码导航显示有 Map[String,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)))
    ))
}

}

但这并不那么优雅...

执行此操作的标准方法是从字段的各个键值对创建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实例将为您完成这项工作。

最新更新