我正在成为play-json海岸到海岸模式的粉丝,特别是它使用组合器。我有一些复杂的案例我正在纠结。我知道有更好的方法,但我是组合方法的新手来构建功能。
我想转此:
{
"somearray": [
{
"field1": "value1",
"field2": "value1",
"key": "key1"
},
{
"field1": "second1",
"field2": "second1",
"key": "key2"
}
]
}
进入这个:
{
"someObj": {
"key1":
{
"field1": "value1",
"field2": "value1"
},
"key2":
{
"field1": "second1",
"field2": "second1"
}
]
}
我可以让这个工作,但我退出转型:
(__ \ "someObj").json.copyFrom(__ \ "someArray".json.pick.map {
case JsArray(arr) => {
JsObject(arr.map(a =>
a.transform(<A transform function to prune key>).map(pruned => {
((a \ "key").as[String], pruned)
}).flatMap({
case JsSuccess(result, _) => Seq(result)
case other => Nil
})
}
case other => JsNull
})
这个代码有一些问题:我知道它很冗长,我知道我假设“key”存在一个字符串类型,我需要flatMap让我脱离JsResult并进入一些JsValue我可以用于构建JsObject。
好像我应该能够
1)创建一个子变换,即a.transform()
可以嵌套在父变换中,而无需解压缩并重新打包json对象。
谢谢。
答案 0 :(得分:1)
这个怎么样(忽略了这个代码仍然存在你已经提到的相同问题的事实)?
def elementTransform = for {
keyValue <- (__ \ 'key).json.pick // picks value for key field
obj <- (__ \ 'key).json.prune // returns object without the key field
res <- (__ \ keyValue.as[String]).json.put(obj) // uses the keyValue as a field name
} yield res
val transform = (__ \ "someObj").json.copyFrom((__ \ "someArray").json.pick[JsArray].map(
_.value.foldLeft[JsResult[JsObject]](JsSuccess(Json.obj()))(
(obj, a) =>
for {
o <- obj
field <- a.transform(elementTransform)
} yield o ++ field
).fold(_ => JsNull, identity)
))