问题
I have a JSON string with array as the following:
{
"cars": {
"Nissan": [
{"model":"Sentra", "doors":4},
{"model":"Maxima", "doors":4}
],
"Ford": [
{"model":"Taurus", "doors":4},
{"model":"Escort", "doors":2}
]
}
}
I would like to edit a new card brand, using circe at scala.
Instead of
"Nissan": [
{"model":"Sentra", "doors":4},
{"model":"Maxima", "doors":4},
]
I would like to have as a result:
"Nissan": [
{"model":"Sentra", "doors":1000},
],
Thanks.
回答1:
Made after reading the manual, please do the same next time!
Apart from your JSON being invalid (Trailing comma on object in array , it should look something like this:"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! (Rerun to see correct indentation!)
newJson
is actually an Option
, so if parsing or modifying fails, you will get None
.
Calling toOption
on parse(json)
converts the returned Either[Json]
(parsing succeeded / failed) to an Option[Json]
.
We need to use an Option[Json]
in the first place because .top
returns a Option[Json]
(modifying succeeded / failed), too.
This way we can flatMap
and don't have to deal with any nested types (see here).
来源:https://stackoverflow.com/questions/52692426/modifying-a-json-array-in-scala-with-circe