JSON Scala 中的对象空过滤

JSON Objects null filtering in scala

我在 Scala (2.12.8) 中使用 play.api.libs.json 来处理一些 json 对象。例如,我有一个 JSON 字符串,看起来像:

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

我想过滤掉每个空字段或子字段。

如此处解释:Play: How to remove the fields without value from JSON and create a new JSON with them

正在做:

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.subfield2field4.subfield2.subsubfield1 仍然存在。我想删除它们。另外我应该提到并不是每个子字段都可以一次为空。如果发生这种情况,我认为我们可以删除上层字段。如果 field3.subfield1field3.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。输出符合预期。