我似乎找不到将Map序列化为JSON对象的正确方法,因为它有不同的值类型,即:
var user: Map[String, Any] = Map("name" -> "1", "id" -> 1)
val json: JsValue = Json.obj(
"user" -> user
)
产生
type mismatch;
found : Map[String,Any]
required: play.api.libs.json.Json.JsValueWrapper
或者,如果我使用Map[String,AnyVal]
,它会产生:
the result type of an implicit conversion must be more specific than AnyVal
但如果我使用Map[String,Number]
或Map[String,String]
则可行。
我缺少什么,是否有一些我可以调用以在JSON.obj()调用中安全地使用数字和整数的包装器?
答案 0 :(得分:5)
根据您的代码段,您需要执行以下操作:
var user = Map("name" -> "1", "id" -> 1)
var json: JsValue = Json.obj(
"user" -> Json.toJson(user)
)
将出现的下一个问题是Play无法为类型writes
找到隐式Map[String, Any]
。
我建议为您尝试序列化的对象编写自己的Writes
。也许如下所示:
case class User(props: Map[String, Any])
implicit val writes: Writes[User] = new Writes[User]{
override def writes(o: User): JsValue = {
val propsJs = JsObject(
o.props.map{kvp =>
kvp._1 -> (kvp._2 match {
case x: String => JsString(x)
case x: Int => JsNumber(x)
case _ => JsNull // Do whatever you want here.
})
}
)
JsObject(Map("user" -> propsJs))
}
}
通过测试:
val u1 = User(Map("name" -> "1", "id" -> 1))
val js = Json.toJson(u1)
out: js: play.api.libs.json.JsValue = {"user":{"name":"1","id":1}}
修改强>
正如评论中所指出的,执行以下操作可能是有利的(取决于您的使用案例):
case class User(name: String, id: Int)
implicit val writes = Json.writes[User]
这更具可读性,更好地巩固了User
的定义。如果你能(我和其他人)能够提出建议,你可能无法做到这一点。