Play-Json Coast-to-Coast:#34; Nesting"的最佳模式转换

时间:2014-12-10 23:21:21

标签: json scala playframework playframework-2.0

我正在成为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对象。

谢谢。

1 个答案:

答案 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)
  ))