Я использую 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
}
}
Вам нужно сделать рекурсивное решение. Например:
def removeNulls(jsObject: JsObject): JsValue = {
JsObject(jsObject.fields.collect {
case (s, j: JsObject) =>
(s, removeNulls(j))
case other if (other._2 != JsNull) =>
other
})
}
Код запускается на Scastie. Выход соответствует ожиданиям.
Вам это нужно как JsObject впоследствии? Вы можете разобрать его в класс case, в котором даже нет этих полей, или эти поля, допускающие значение NULL в качестве опции, а отсутствующие или пустые поля будут проанализированы как None.