6

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!

Xavier Guihot
  • 54,987
  • 21
  • 291
  • 190

1 Answers1

2

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))
}
Octavian R.
  • 1,231
  • 8
  • 12
  • thanks for the anwser, but it's quite boilerplate'y to define mappings for every field, would be nice to just have some implicit way of mapping them instead – Evaldas Miliauskas May 11 '18 at 04:35
  • The code can be generalized using shapeless. I will try to provide an example in the next days. I don't think that it's possible without some boilerplate code. – Octavian R. May 11 '18 at 06:52
  • ah ok, that would be interesting. Yes I guess preserving types requires explicit handling one way or another. – Evaldas Miliauskas May 13 '18 at 06:47