如何使用Play JSON通过键值从非结构化JSON中删除对象

时间:2018-10-24 11:58:21

标签: json scala playframework play-json

我有许多非结构化json。例如:

{
  "peoples": [
    {
      "name": "Vasya",
      "age": 33
    },
    {
      "name": "Petya",
      "age": 40,
      "childs": [
        {
          "name": "Vasya",
          "age": 33
        }
      ]
    }
  ],
  "notPeoples": [
    {
      "name": "Vasya",
      "kind": "starship"
    },
     {
      "name": "Iq441",
      "kind": "car"
    }
  ]
}

我需要删除所有对象,其中name = "Vasya"。请注意,它可以是具有任何模式的json(不仅是人-某些对象具有“名称”字段的json),因此我应该分析每个对象(数组中的数组等)。

结果应为:

{
  "peoples": [
    {
      "name": "Petya",
      "age": 40,
      "childs": []
    }
  ],
  "notPeoples": [
    {
      "name": "Iq441",
      "kind": "car"
    }
  ]
}

如何通过play json转换实现这一目标?也许还有另一个Java / scala库。

1 个答案:

答案 0 :(得分:1)

该示例未生成您发布的确切JSON,但我想您已经知道如何使用play.json过滤任意JSON:

def filterByName(name: String, filter: JsValue, js: JsValue): JsValue = js match {
    case JsArray(vs) => JsArray(vs.map(filterByName(name, filter, _)))
    case JsObject(vs) =>
      JsObject(vs.flatMap { case (key, value) =>
          if (key == name && value == filter) None
          else Some(key -> filterByName(name, filter, value))
      })
    case otherwise => otherwise
  }

def filterByString(name: String, value: String, js: JsValue): JsValue =
  filterByName(name, JsString(value), js)

编辑: 如果我正确理解了您的用例,则可以实现如下所示的过滤器逻辑-上面的示例从输入JSON过滤单个元素,而该示例过滤“环绕”对象,以防其元素满足谓词:

def filterObjElements(name: String, value: JsValue, js: JsValue): JsValue = {
  def filter(current: JsValue): Option[JsValue] = current match {
    case JsArray(vs) => Some(JsArray(vs.flatMap(filter)))
    case JsObject(vs) =>
      if (vs.exists { case (key, value0) => key == name && value0 == value})
        None
      else {
        Some(JsObject(vs.flatMap { case (key, value0) =>
          filter(value0).map(key -> _)
        }))
      }
    case otherwise => Some(otherwise)
  }

  js match {
    case arr: JsArray => filter(arr).getOrElse(JsArray())
    case obj: JsObject => filter(obj).getOrElse(JsObject(Nil))
    case otherwise => otherwise
  }
}

def filterObjElements(name: String, value: String, js: JsValue): JsValue =
  filterObjElements(name, JsString(value), js)