3

I am using circe optics like this

import io.circe.parser._
import io.circe.optics._
import io.circe.optics.JsonPath._

val json = parse("""{"response": {"person": {"firstname": "foo", "lastname":"bar"}}}""").right.get

Now I want to extract the whole person object in string form ... from this json like

val p = root.response.person.string

and then decode it into a case class like

case class Person(firstname: String, lastname: String)
decode[Person](p.getOption(json).get)

But it doesn't work because root.response.person.string returns null. I think it only works on actual string and integer columns.

So can circe optics be used to extract entire sections of json (for example the person object inside of json)? and then that section is decoded into a case class?

Knows Not Much
  • 30,395
  • 60
  • 197
  • 373

1 Answers1

2

This gets it done. No need to get the string in between, just work with the Json

object Some extends App {

  import io.circe.optics.JsonPath._
  import io.circe.parser._
  import io.circe._
  import io.circe.generic.semiauto._

  val json = parse("""{"response": {"person": {"firstname": "foo", "lastname":"bar"}}}""").right.get

  // this is just a lense to the person, not the person yet
  val personJsonPath = root.response.person.json

  case class Person(firstname: String, lastname: String)
  implicit val personDecoder: Decoder[Person] = deriveDecoder[Person]

  val maybePerson = personJsonPath
    // here you get the person out
    .getOption(json)
    // transforming json directly to case class, error handling should not be done like this ;)
    .map(_.as[Person].fold(throw _, identity))

  println(maybePerson)
}
rincewind
  • 623
  • 6
  • 13