如何使用circe在Scala中解码JSON并忽略字段名称的大小写敏感性

6
我有一个失败的测试用例如下:

我有以下无法通过的测试用例:

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)
}

解码失败并报错:
LeftProjection(Left(DecodingFailure([A]List[A], List(DownField(action), DownArray))))

解码器是否可以忽略大小写映射字段?或者使用decoder.prepare以优雅的方式处理这个问题,有什么好方法吗?

谢谢!


你解决了吗? - eirirlar
1个回答

2
您可以尝试以下代码:
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))
}

谢谢您的回答,但是为每个字段定义映射有点模板化了。希望能够有一种隐式的方式来映射它们。 - Evaldas Miliauskas
代码可以使用shapeless进行泛化。我会在接下来的几天里尝试提供一个例子。我认为这是不可能没有一些样板代码的。 - Octavian R.
啊,好的,那会很有趣。是的,我猜保留类型需要明确处理一种方式或另一种方式。 - Evaldas Miliauskas

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接