当我在 REPL 中执行时,它可以工作(由于作用域中的隐式mapWrites
):
scala> Map("a"->1l, "b"->2l)
res0: scala.collection.immutable.Map[String,Long] = Map(a -> 1, b -> 2)
scala> Map("c" -> res0, "d" -> res0)
res1: scala.collection.immutable.Map[String,scala.collection.immutable.Map[String,Long]] = Map(c -> Map(a -> 1, b -> 2), d -> Map(a -> 1, b -> 2))
scala> import play.api.libs.json._
import play.api.libs.json._
scala> Json.toJson(res1)
res2: play.api.libs.json.JsValue = {"c":{"a":1,"b":2},"d":{"a":1,"b":2}}
为什么我的代码仍然无法编译(它与 REPL 中的类型相同)?
No Json deserializer found for type Map[String,Map[String,Long]]. Try to implement an implicit Writes or Format for this type.
[编辑] 我找到了解决方法,但我不明白为什么我需要它:
implicit def mapWrites = Writes[Map[String,Map[String,Long]]] ( m => Writes.mapWrites(Writes.mapWrites[Long]).writes(m))
Play 2.1 JSON API 不提供类型 Map[String, Object]
的序列化程序。
为特定类型定义case class
和Format
,而不是Map[String, Object]
:
// { "val1" : "xxx", "val2" : ["a", "b", "c"] }
case class Hoge(val1: String, val2: List[String])
implicit val hogeFormat = Json.format[Hoge]
如果您不想创建案例类。以下代码为 Map[字符串,对象] 提供 JSON 序列化程序/反序列化程序:
implicit val objectMapFormat = new Format[Map[String, Object]] {
def writes(map: Map[String, Object]): JsValue =
Json.obj(
"val1" -> map("val1").asInstanceOf[String],
"val2" -> map("val2").asInstanceOf[List[String]]
)
def reads(jv: JsValue): JsResult[Map[String, Object]] =
JsSuccess(Map("val1" -> (jv "val1").as[String], "val2" -> (jv "val2").as[List[String]]))
}
杰克逊不知道如何反序列化Scala集合类scala.collection.immutable.Map
,因为它没有实现任何Java集合接口。
您可以反序列化为 Java 集合:
val mapData = mapper.readValue(jsonContent, classOf[java.util.Map[String,String]])
或者将 Scala 模块添加到映射器中:
mapper.registerModule(DefaultScalaModule)
val mapData = mapper.readValue(jsonContent, classOf[Map[String,String]])
或者你也可以这样尝试
import play.api.libs.json._
val a1=Map("val1"->"a", "val2"->"b")
Json.toJSon(a1)
因为 a1 只是工作正常的Map[String,String]
。
但是如果我有更复杂的东西,比如我有Map[String,Object]
的地方,那是行不通的:
val a = Map("val1" -> "xxx", "val2"-> List("a", "b", "c"))
Json.toJSon(a1)
>>> error: No Json deserializer found for type scala.collection.immutable.Map[String,Object]
我发现我可以做如下事情:
val a2 = Map("val1" -> Json.toJson("a"), "val2" -> Json.toJson(List("a", "b", "c")))
Json.toJson(a2)
这行得通。