Search code examples
jsonscalacirce

Decoding a Seq of objects using Circe


I have two classes that look something like that

import io.circe.Decoder

case class FactResponse(id: String, status: String) {
  ...
}


object FactResponse {

  implicit val decoder: Decoder[FactResponse] =
    Decoder.forProduct2("id", "status")(FactResponse.apply)

  def apply(json: String): FactResponse = {
    import io.circe.parser.decode
    decode[FactResponse](json).right.get
  }
}    



case class RuleEngineRequestResponse(content: Seq[Map[String, String]])

object RuleEngineRequestResponse {

  implicit val decoder: Decoder[RuleEngineRequestResponse] =
    Decoder.forProduct1("content")(RuleEngineRequestResponse.apply(_: String))

  def apply(json: String): RuleEngineRequestResponse = {
    import io.circe.parser.decode
    println("here")
    print(json)
    println(decode[RuleEngineRequestResponse](json).left.get)
    decode[RuleEngineRequestResponse](json).right.get
  }
}

I am trying to decode a json that looks something like this

{ "content" :[{"id":"22", "status":"22"]}

However, I am getting a decoding failure DecodingFailure(String, downfield("content"))

I am not really sure what is going wrong here, the json is definitely a correct one, I even tried to parse the content into a sequence of maps but still, I get the same thing over and over again. any idea on how to parse nested objects as an array using circe?


Solution

  • I think you can simplify the decoding a lot if you let circe derive the decoders automatically:

    import io.circe.generic.auto._
    import io.circe.parser.decode
    
    case class FactResponse(id: String, status: String)
    case class RuleEngineRequestResponse(content: Seq[FactResponse])
    
    object Sample extends App {
      val testData1 =
        """
          |{
          |   "content":[
          |      {
          |         "id":"22",
          |         "status":"22"
          |      }
          |   ]
          |}""".stripMargin
    
      val testData2 =
        """
          |{
          |   "content":[
          |      {
          |         "id":"22",
          |         "status":"22"
          |      },
          |      {
          |         "id":"45",
          |         "status":"56"
          |      }
          |   ]
          |}""".stripMargin
    
      println(decode[RuleEngineRequestResponse](testData1))
      println(decode[RuleEngineRequestResponse](testData2))
    
    }
    

    This outputs:

    Right(RuleEngineRequestResponse(List(FactResponse(22,22))))
    Right(RuleEngineRequestResponse(List(FactResponse(22,22), FactResponse(45,56))))
    

    You will need to include dependencies:

      "io.circe" %% "circe-generic" % circeVersion,
      "io.circe" %% "circe-parser"  % circeVersion,
    

    I used circe version 0.10.0

    You can check it out here.