【问题标题】:How to remove objects from unstructured json by key-value with play json如何使用 play json 通过键值从非结构化 json 中删除对象
【发布时间】:2018-10-26 01:46:32
【问题描述】:

我有很多非结构化的 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 库。

【问题讨论】:

  • 如果在 JSON 对象中随机命名字段(“peoples”、“notPeoples”、“foo”、“bar”等),您将遇到麻烦。我所知道的库不能迭代 JSON 对象内的字段——而是迭代 JSON 数组。您的顶级 JSON 对象不能是数组是否有原因?
  • 在我的例子中,顶级 json 可以是任何类型。
  • @zella,您能否发布解决方案以防万一解决。

标签: json scala playframework play-json


【解决方案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)

【讨论】:

    猜你喜欢
    • 2018-07-06
    • 2014-09-06
    • 1970-01-01
    • 2018-03-17
    • 1970-01-01
    • 2021-12-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多