我有以下(简化)结构:
case class MyKey(key: String)
case class MyValue(value: String)
我们假设我有两个案例类的Play JSON格式化程序。
作为一个例子,我有:
val myNewMessage = collection.immutable.Map(MyKey("key1") -> MyValue("value1"), MyKey("key2") -> MyValue("value2"))
由于以下转型
play.api.libs.json.Json.toJson(myNewMessage)
我期待的是:
{ "key1": "value1", "key2": "value2" }
我曾尝试编写格式化程序,但不知怎的,我无法成功:
implicit lazy val mapMyKeyMyValueFormat: Format[collection.immutable.Map[MyKey, MyValue]] = new Format[collection.immutable.Map[MyKey, MyValue]] {
override def writes(obj: collection.immutable.Map[MyKey, MyValue]): JsValue = Json.toJson(obj.map {
case (key, value) ⇒ Json.toJson(key) -> Json.toJson(value)
})
override def reads(json: JsValue): JsResult[collection.immutable.Map[MyKey, MyValue]] = ???
}
我不知道如何编写正确的reads
函数。有没有更简单的方法呢?我对writes
功能也不满意。
THX!
答案 0 :(得分:1)
writes
方法无效的原因是因为您正在将Map[MyKey, MyValue]
转换为Map[JsValue, JsValue]
,但您无法将其序列化为JSON。 JSON键需要是字符串,因此您需要某种方式将MyKey
转换为某个唯一的String
值。否则你会尝试序列化这样的东西:
{"key": "keyName"} : {"value": "myValue"}
哪个是无效的JSON。
如果MyKey
与您的问题中所述的一样简单,则可以这样做:
def writes(obj: Map[MyKey, MyValue]): JsValue = Json.toJson(obj.map {
case (key, value) => key.key -> Json.toJson(value)
}) // ^ must be a String
在给定相应Map[String, MyValue]
的情况下,播放将知道如何序列化Writes[MyValue]
。
但我不确定那是你想要的。因为它产生了这个:
scala> Json.toJson(myNewMessage)
res0: play.api.libs.json.JsValue = {"key1":{"value":"value1"},"key2":{"value":"value2"}}
如果这是您想要的输出:
{ "key1": "value1", "key2": "value2" }
然后你的Writes
应该更像这样:
def writes(obj: Map[MyKey, MyValue]): JsValue = {
obj.foldLeft(JsObject(Nil)) { case (js, (key, value)) =>
js ++ Json.obj(key.key -> value.value)
}
}
产生这个:
scala> writes(myNewMessage)
res5: play.api.libs.json.JsValue = {"key1":"value1","key2":"value2"}
只要Reads
和MyKey
的结构相同, MyValue
就很容易,否则我不知道你想要它做什么。它非常依赖于您想要的实际结构。因此,我建议利用现有的Reads[Map[String, String]]
并将其转换为您想要的类型。
def reads(js: JsValue): JsResult[Map[MyKey, MyValue]] = {
js.validate[Map[String, String]].map { case kvMap =>
kvMap.map { case (key, value) => MyKey(key) -> MyValue(value) }
}
}
如果不了解数据的实际结构,很难看到很多其他内容。一般来说,我不必序列化和反序列化Map
s。