Play Framework Json 递归转换

Play Framework Json Transform recursivly

一段时间以来,我一直在解决以下问题。

我尝试通过 tree-like json 结构进行递归转换。

{
    "id": 21,
    "title": "Title1",
    "children": [
        {
            "id": 22,
            "title": "Title1.1",
            "children": [
                {
                    "id": 33,
                    "title": "Title1.1.1",
                    "children": [
                        {
                            "id": 41,
                            "title": "Title1.1.1.1",
                            "children": [
                                {
                                    "id": 42,
                                    "title": "Title1.1.1.1.1",
                                }
                            ]
                        }
                    ]
                }
            ]
        }
    ]
}

到目前为止我有:

  val idChanger:Reads[JsObject] = (__ \ 'id).json.update(of[JsNumber].map{case JsNumber(nb) => JsNumber(nb * 100)})

  val childPicker:Reads[JsValue] = (__ \ 'children).json.pick[JsArray].map{
    case JsArray(arr) => JsArray(arr.map(o => {
      o.transform(idChanger) match {
        case JsSuccess(value, jsPath) =>
          println(s"Success:$value")
          value
        case JsError(errors) =>
          println(s"Error:$errors"); JsNull
      }
    }))
  }

val jsvalue: JsValue = ...
jsvalue.transform(childPicker)
...

这仅适用于第一层,并相应地更改 ID“21”,但到目前为止还不能更改其余部分。

我也尝试了很多不同的方法来递归完成 children 的其余部分,但到目前为止没有成功。

如有任何帮助,我们将不胜感激。

干杯,罗伯

只需在 Reads 中添加递归调用,并确保处理 JsArray 和 JsObject。这是一个符合这个基本思想的简单例子。

val idChanger: Reads[JsObject] =
  (__ \ 'id).json.update(of[JsNumber].map{case JsNumber(nb) => JsNumber(nb * 100)})


val picker: Reads[JsValue] = __.json.pick.map{
  case JsArray(arr) => JsArray(arr.map(_.transform(picker).get))
  case v: JsValue =>
    v.transform(
      idChanger andThen (__ \ "children").json.update(picker) orElse
      idChanger
  ).get
}