Нулевая фильтрация объектов JSON в scala

Я использую play.api.libs.json в Scala (2.12.8) для обработки некоторых объектов json. У меня есть, например, строка JSON, которая выглядит так:

{
  "field1": null,
  "field2": 23,
  "field3": {
    "subfield1": "a",
    "subfield2": null
  },
  "field4": {
    "subfield1": true,
    "subfield2": {
      "subsubfield1": null,
      "subsubfield2": "45"
    },
    "field5": 3
  }
}

И я хочу отфильтровать все нулевые поля или подполя.

Как объяснено здесь: Игра: Как удалить поля без значения из JSON и создать с ними новый JSON

Делает:

import play.api.libs.json.{ JsNull, JsObject, JsValue, Json }

val j = Json.parse(myJsonString).as[JsObject]
JsObject(j.fields.filterNot(t => withoutValue(t._2)))

def withoutValue(v: JsValue) = v match {
  case JsNull => true
  case _      => false
}

помогает мне удалить поля верхнего уровня: в моем случае field1

Но field3.subfield2 и field4.subfield2.subsubfield1 все еще присутствуют. Я хочу удалить их. Также я должен упомянуть, что не все подполя могут быть нулевыми одновременно. Если это произойдет, я думаю, мы могли бы просто удалить поле верхнего уровня. Если field3.subfield1 и field3.subfield2 равны нулю, мы можем удалить field3.

Любая идея о том, как сделать это аккуратно в Scala?

PS: желаемый результат:

{
  "field2": 23,
  "field3": {
    "subfield1": "a"
  },
  "field4": {
    "subfield1": true,
    "subfield2": {
      "subsubfield2": "45"
    },
    "field5": 3
  }
}

Вам это нужно как JsObject впоследствии? Вы можете разобрать его в класс case, в котором даже нет этих полей, или эти поля, допускающие значение NULL в качестве опции, а отсутствующие или пустые поля будут проанализированы как None.

Saskia 10.12.2020 10:51
Как сделать HTTP-запрос в Javascript?
Как сделать HTTP-запрос в Javascript?
В JavaScript вы можете сделать HTTP-запрос, используя объект XMLHttpRequest или более новый API fetch. Вот пример для обоих методов:
0
1
511
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вам нужно сделать рекурсивное решение. Например:

def removeNulls(jsObject: JsObject): JsValue = {
  JsObject(jsObject.fields.collect {
    case (s, j: JsObject) =>
      (s, removeNulls(j))
    case other if (other._2 != JsNull) =>
      other
  })
}

Код запускается на Scastie. Выход соответствует ожиданиям.

Другие вопросы по теме