Как удалить объекты из неструктурированного json по ключу с помощью play json - PullRequest
0 голосов
/ 24 октября 2018

У меня много неструктурированных jsons.Например:

{
  "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, где у некоторых объектов есть поле «name»), поэтому я должен проанализировать каждый объект (массив в массиве и т. Д.).

Результат должен быть:

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

Как этого добиться с помощью преобразования json play?Или, может быть, с другой java / scala libs.

1 Ответ

0 голосов
/ 24 октября 2018

Пример не дает точный JSON, который вы опубликовали, но я думаю, вы поймете, как фильтровать произвольный JSON с помощью play.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)
...