【问题标题】:how to decode json in scala with circe by ignoring fieldname case sensitivity如何通过忽略字段名区分大小写来使用 circe 解码 scala 中的 json
【发布时间】:2017-09-06 17:34:47
【问题描述】:

我有以下失败的测试用例:

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处理这个?

谢谢!

【问题讨论】:

  • 你弄明白了吗?

标签: json scala circe


【解决方案1】:

你可以试试下面的代码:

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

【讨论】:

  • 感谢您的回答,但是为每个字段定义映射是非常样板的,如果有一些隐式的映射方式来代替它们会很好
  • 代码可以用shapeless进行泛化。我会在接下来的几天里尝试提供一个例子。我认为没有一些样板代码是不可能的。
  • 啊好吧,那会很有趣。是的,我想保留类型需要以一种或另一种方式进行显式处理。
猜你喜欢
  • 2017-09-01
  • 2022-07-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-16
  • 1970-01-01
  • 2020-08-12
  • 2016-11-11
相关资源
最近更新 更多