Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to decode json in scala with circe by ignoring fieldname case sensitivity

Tags:

json

scala

circe

I have the following failing test case:

case class ActionRequest(action: String, `type`:String, key: String)

"Actions " should " be decoded correctly" in {
    val actionJson =
      """[
        |{"Action":"view","Type":"Product","Key":"1210"},
        |{"action":"filter","type":"by-price","key":"low-hi"}
        |]
        |""".stripMargin
    val actions = decode[List[ActionRequest]](actionJson).right.getOrElse(List())
    assert(actions.size == 2)
}

decoding fails with error:

LeftProjection(Left(DecodingFailure([A]List[A], List(DownField(action), DownArray))))

Is it possible for the decoder to map fields ignoring the case sensitivity? Or maybe there is an elegant way handle this with decoder.prepare?

Thanks!

like image 838
Evaldas Miliauskas Avatar asked Nov 07 '22 23:11

Evaldas Miliauskas


1 Answers

You can try the following code:

import io.circe._
import io.circe.generic.auto._

object CirceApp extends App {

    val actionJson = """[
      {"Action":"view","Type":"Product","Key":"1210"},
      {"action":"filter","type":"by-price","key":"low-hi"}
    ]""".stripMargin

    case class ActionRequest(action: String, `type`: String, key: String)

    implicit val decodeActionJson: Decoder[ActionRequest] = (c: HCursor) => {
        val keysMapping = c.keys.get.groupBy(_.toLowerCase).map(kv => (kv._1, kv._2.head))
        for {
            actionField <- c.downField(keysMapping("action")).as[String]
            typeField <- c.downField(keysMapping("type")).as[String]
            keyField <- c.downField(keysMapping("key")).as[String]
        } yield {
          ActionRequest(actionField, typeField, keyField)
        }
    }

    println(decode[Seq[ActionRequest]](actionJson))
}
like image 121
Octavian R. Avatar answered Nov 14 '22 20:11

Octavian R.