使用circe在Scala中修改JSON数组

时间:2018-10-07 20:07:48

标签: scala circe

我有一个带有数组的JSON字符串,如下所示:

{
"cars": {
    "Nissan": [
        {"model":"Sentra", "doors":4},
        {"model":"Maxima", "doors":4}
    ],
    "Ford": [
        {"model":"Taurus", "doors":4},
        {"model":"Escort", "doors":2}
    ]
}
}

我想使用Scala中的 编辑新的卡片品牌。
代替

"Nissan": [
        {"model":"Sentra", "doors":4},
        {"model":"Maxima", "doors":4},
    ]

我希望得到这样的结果:

"Nissan": [
        {"model":"Sentra", "doors":1000},
    ],

谢谢。

1 个答案:

答案 0 :(得分:0)

阅读manual之后,请再次执行相同的操作!

除了您的JSON无效(对数组"Nissan"中的对象使用逗号逗号)之外,它应该类似于以下内容:

import cats.syntax.either._
import io.circe._, io.circe.parser._

val json: String = """
{
"cars": {
    "Nissan": [
        {"model":"Sentra", "doors":4},
        {"model":"Maxima", "doors":4}
    ],
    "Ford": [
        {"model":"Taurus", "doors":4},
        {"model":"Escort", "doors":2}
    ]
}
}
"""

val newJson = parse(json).toOption
  .flatMap { doc =>
    doc.hcursor
      .downField("cars")
      .downField("Nissan")
      .withFocus(_ =>
          Json.arr(
            Json.fromFields(
              Seq(
                ("model", Json.fromString("Sentra")),
                ("doors", Json.fromInt(1000))
              )
            )
          )
      )
      .top
  }

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

Try it out!(重新运行以查看正确的缩进!)


newJson实际上是一个Option,因此如果解析或修改失败,您将得到None

toOption上调用parse(json)会将返回的Either[Json](解析成功/失败)转换为Option[Json]

我们首先需要使用Option[Json],因为.top也会返回Option[Json](修改成功/失败)。

通过这种方式,我们可以flatMap,而不必处理任何嵌套类型(see here)。