简体   繁体   English

如何通过 Scala 删除空 json object

[英]how to remove empty json object by Scala

some times we have JSON looks like this: {a:{}, b:{c:{}, d:123}}有时我们的 JSON 看起来像这样: {a:{}, b:{c:{}, d:123}}

you want to remove the empty structures and make it into {b:{d:123}}您想删除空结构并将其放入{b:{d:123}}

here is how you can do it simply in Scala by using Jackson:以下是您如何使用 Jackson 在 Scala 中简单地做到这一点:

val json = """ {"a":{}, "b": {"c": {}, "d": 123}} """
val mapper = new ObjectMapper()
mapper
  .setSerializationInclusion(JsonInclude.Include.NON_EMPTY)
  .setSerializationInclusion(JsonInclude.Include.NON_NULL)
  .setSerializationInclusion(JsonInclude.Include.NON_ABSENT)
val node = mapper.readTree(json)
removeEmptyFields(node)
val cleanJson = mapper.writeValueAsString(node) // {"b": {"d": 123}}

  private def removeEmptyFields(obj: Object): Boolean = {
    if (obj.isInstanceOf[ArrayNode]) {
      val array = obj.asInstanceOf[ArrayNode]

      val iter = array.elements()
      var i = 0
      while (iter.hasNext) {
        if(!removeEmptyFields(iter.next())) array.remove(i)

        i += 1
      }

      true
    } else if (obj.isInstanceOf[ObjectNode]) {
      val json = obj.asInstanceOf[ObjectNode]
      val names = json.fieldNames().asScala.toList
      if (names == null || names.isEmpty) return false

      var removeRoot = true

      names.foreach (
        name => {
          if (!removeEmptyFields(json.get(name))) {
            json.remove(name)
          } else removeRoot = false
        }
      )

      !removeRoot
    } else true
  }

Pure, stack-safe implementation with circe :使用circe的纯堆栈安全实现:

import cats.Eval
import cats.implicits._
import io.circe.JsonObject
import io.circe.literal._
import io.circe.syntax._

object Main extends App {
  def removeEmpty(jo: JsonObject): JsonObject = {
    //`Eval` is trampolined so this is stack-safe
    def loop(o: JsonObject): Eval[JsonObject] =
      o.toList.foldLeftM(o) { case (acc, (k, v)) =>
        v.asObject match {
          case Some(oo) if oo.isEmpty =>  acc.remove(k).pure[Eval]
          case Some(oo)               =>  Eval.defer(loop(oo)).map(_o => acc.add(k, _o.asJson))
          case _                      =>  acc.pure[Eval]
        }
      }

    loop(jo).value
  }

  //this is a json literal
  // if it's from a dynamic string please parse it with `io.circe.parser.parse` first
  val json = json"""{"a":{}, "b": {"c": {}, "d": 123}}"""

  val res = json.asObject.map(removeEmpty(_).asJson)

  println(res)
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM