我正在使用Play framework 2.2.2。 我试图像这样处理json请求
[
{
"id" : "123",
"language" : "en",
"text" : "This is an example of a text",
"Metadata_IP" : "192.168.20.34",
"Metadata_date" : "2001-07-04T12:08:56.235-0700"
},
{
"id" : "124",
"language" : "en",
"text" : "Some more text here",
"Metadata_IP" : "192.168.20.31",
"Metadata_date" : "2001-07-04T12:09:56.235-0700",
"Metadata_name" : "someone"
}
]
Metadata_字段是动态字段,意味着用户可以发送他想要的内容(例如,Metadata_color等...) 处理这个问题的最佳方法是什么?
我可以使用Readers将其反序列化为case class吗?我怎样才能做到这一点?我想动态字段将是Map [String,String],但我该如何让读者解析这个?
由于
答案 0 :(得分:5)
这样的事情可行:
implicit object jsObjToKeyValueSeq extends Reads[Seq[(String, String)]] {
override def reads(json: JsValue) = json match {
case js: JsObject =>
JsSuccess(js.fields.collect { case (key, JsString(value)) => key -> value })
case x => JsError(s"Unexpected json: $x")
}
}
答案 1 :(得分:0)
我们遇到了确切的问题,并使用自定义实现解决了它。解决方案详细here
示例:
Scala类
case class Person(name: String, age: String, customFields: Map[String,String])
上述类的默认Json表示形式为:
{
"name": "anil",
"age": "30",
"customFields": {
"field1": "value1",
"field2": "value2"
}
}
但我们想要的是:
{
"name": "anil",
"age": "30",
"field1": "value1",
"field2": "value2"
}
这不是很直接。虽然使用play框架可以实现这一点,但我们并不想让事情太复杂化。最后,我们通过返回Map [String,String]找到了一种方法,它使用反射代表每个类(它的字段和值)并分别处理自定义字段的行为。
case class Person(name: String, age: String, customFields:CustomFields)
case class CustomFields(valueMap: Map[String,String])
def covertToMap(ref: AnyRef) =
ref.getClass.getDeclaredFields.foldLeft(Map[String, Any]()){
(map, field) => {
field.setAccessible(true)
val value = field.get(ref)
value match {
case c: CustomFields => {
map ++ c.valueMap
}
case _ => {
map + (field.getName -> value)
}
}
}
}
使用covertToMap()将任何案例类转换为Map,然后使用jackson json4s将此映射转换为普通Json。
val json = Serialization.write(covertToMap(person))
完整的源代码可用here