如何使用 Circe 将空对象插入 JSON?

How to insert an empty object into JSON using Circe?

我正在通过网络获取一个 JSON 对象,作为字符串。然后我使用 Circe 来解析它。我想在其中添加一些字段,然后将其传递给下游。

几乎所有这些都有效。

问题是我的 "adding" 真的是 "overwriting"。其实没关系,只要我先添加一个空对象即可。如何添加这样一个空对象?

所以看看下面的代码,我正在覆盖 "sometimes_empty:{}" 并且它有效。但是因为 sometimes_empty 并不总是空的,所以会导致一些数据丢失。我想添加一个字段,例如:"custom:{}",然后用我现有的代码覆盖自定义的值。

两篇 Whosebug 帖子很有帮助。一个有效,但不是我想要的。另一个我无法上班。

1: Modifying a JSON array in Scala with circe

2: Adding field to a json using Circe

val js: String = """
{
  "id": "19",
  "type": "Party",
  "field": {
    "id": 1482,
    "name": "Anne Party",
    "url": "https"
  },
  "sometimes_empty": {

  },
  "bool": true,
  "timestamp": "2018-12-18T11:39:18Z"
}
"""

val newJson = parse(js).toOption
  .flatMap { doc =>
    doc.hcursor
      .downField("sometimes_empty")
      .withFocus(_ =>
        Json.fromFields(
          Seq(
            ("myUrl", Json.fromString(myUrl)),
            ("valueZ", Json.fromString(valueZ)),
            ("valueQ", Json.fromString(valueQ)),
            ("balloons", Json.fromString(balloons))
          )
        )
      )
      .top
  }

newJson match {
  case Some(v) => return v.toString
  case None => println("Failure!")
}

我们需要做几件事。首先,我们需要放大我们要更新的特定 属性,如果它不存在,我们将创建一个新的空的。然后,我们将Json形式的放大的属性变成JsonObject,以便能够使用+:方法修改。完成后,我们需要获取更新的 属性 并在原始解析的 JSON 中重新引入它以获得完整的结果:

import io.circe.{Json, JsonObject, parser}
import io.circe.syntax._

object JsonTest {
  def main(args: Array[String]): Unit = {
    val js: String =
      """
        |{
        |  "id": "19",
        |  "type": "Party",
        |  "field": {
        |    "id": 1482,
        |    "name": "Anne Party",
        |    "url": "https"
        |  },
        |  "bool": true,
        |  "timestamp": "2018-12-18T11:39:18Z"
        |}
      """.stripMargin

    val maybeAppendedJson =
      for {
        json <- parser.parse(js).toOption
        sometimesEmpty <- json.hcursor
          .downField("sometimes_empty")
          .focus
          .orElse(Option(Json.fromJsonObject(JsonObject.empty)))
        jsonObject <- json.asObject
        emptyFieldJson <- sometimesEmpty.asObject
        appendedField = emptyFieldJson.+:("added", Json.fromBoolean(true))
        res = jsonObject.+:("sometimes_empty", appendedField.asJson)
      } yield res

    maybeAppendedJson.foreach(obj => println(obj.asJson.spaces2))
  }
}

产量:

{
  "id" : "19",
  "type" : "Party",
  "field" : {
    "id" : 1482,
    "name" : "Anne Party",
    "url" : "https"
  },
  "sometimes_empty" : {
    "added" : true,
    "someProperty" : true
  },
  "bool" : true,
  "timestamp" : "2018-12-18T11:39:18Z"
}