-2

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.

3
  • 1
    what have you tried to do so far? where 1000 come from? Commented Oct 7, 2018 at 20:27
  • 1
    I think the easiest way to go would be to decode the json string first, do all the transformations on the scala objects directly and encode the result back to json again. Commented Oct 8, 2018 at 9:48
  • Apart from asking a perfectly valid question, try to read into documentation and attempt to solve your problem before coming to StackOverflow. Once you come to the point of asking a question here, list what you have looked into and any code snippets that you wrote while doing so, even if they don't work. StackOverflow doesn't write your code, it tries to help you where you are stuck. This is not to annoy you, but to get you to learn to do it yourself. Commented Oct 8, 2018 at 14:43

1 Answer 1

1

Made after reading the manual, please do the same next time!

Apart from your JSON being invalid (Trailing comma on object in array "Nissan"), it should look something like this:

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).

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.