Search code examples
scalacirce

Parse Json from snake case to camel case


So I have a JSON in this format which I am trying to convert from snake case to camel case matching a corresponding case class

 val json = """
      {
        "items": [
        {
          "id": "7913",
          "route_id": "33",
          "predictable": true,
          "run_id": "33_486_1",
          "latitude": 34.0234949,
          "longitude": -118.398712,
          "heading": 236,
          "seconds_since_report": 59
        },
        {
          "id": "4140",
          "route_id": "76",
          "predictable": true,
          "run_id": "76_174_0",
          "latitude": 34.0331945,
          "longitude": -118.2646534,
          "heading": 122,
          "seconds_since_report": 12
        },
        {
          "id": "7620",
          "route_id": "20",
          "predictable": true,
          "run_id": "20_669_0",
          "latitude": 34.013733,
          "longitude": -118.490067,
          "heading": 334,
          "seconds_since_report": 172
        }
        ]
      }
      """.stripMargin

which I want converted to

  final case class Sample(
    id: Int,
    routeId: Int,
    predictable: Boolean,
    runId: String,
    latitude: Double,
    longitude: Double,
    heading: Int,
    secondsSinceReport: Int
  )

Tried using

implicit val sampleDecoder = Decoder[List[Sample]].prepare(_.downField("items"))
val decodingResult = parser.decode(json)(sampleDecoder)

but the result comes as

Attempt to decode value on failed cursor: DownField(routeId),DownArray,DownField(items)

however if I comment out the fields with camel case from the case class I get

Sample(7913,true,34.0234949,-118.398712,236)
Sample(4140,true,34.0331945,-118.2646534,122)
Sample(7620,true,34.013733,-118.490067,334)

Solution

  • Finally figured it out without

    
    implicit val encoder : Encoder[Sample] = 
        Encoder.forProduct8(
          "id",
          "route_id",
          "predictable",
          "run_id",
          "latitude",
          "longitude",
          "heading",
          "seconds_since_report"
        )(Sample.unapply(_).get)
    
      implicit val decoder : Decoder[Sample] =
        Decoder.forProduct8(
          "id",
          "route_id",
          "predictable",
          "run_id",
          "latitude",
          "longitude",
          "heading",
          "seconds_since_report"
        )(Sample.apply)
    
    
    
       implicit val sampleDecoder = Decoder[List[Sample]].prepare(_.downField("items"))
       val decodingResult = parser.decode(json)(sampleDecoder)
    
       decodingResult match {
            case Left(value) => println(value.getMessage())
            case Right(value) => value.foreach(println)
       }
    
    

    And the result matches the supplied json

    Sample(7913,33,true,33_486_1,34.0234949,-118.398712,236,59)
    Sample(4140,76,true,76_174_0,34.0331945,-118.2646534,122,12)
    Sample(7620,20,true,20_669_0,34.013733,-118.490067,334,172)