首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Circe从蛇案例密钥中解析json

Circe从蛇案例密钥中解析json
EN

Stack Overflow用户
提问于 2019-04-26 11:52:30
回答 2查看 4.2K关注 0票数 8

我有以下案例课:

代码语言:javascript
复制
final case class Camel(firstName: String, lastName: String, waterPerDay: Int)

和circe配置:

代码语言:javascript
复制
object CirceImplicits {

  import io.circe.syntax._
  import io.circe.generic.semiauto._
  import io.circe.{Encoder, Decoder, Json}
  import io.circe.generic.extras.Configuration

  implicit val customConfig: Configuration =
    Configuration.default.withSnakeCaseMemberNames.withDefaults
  implicit lazy val camelEncoder: Encoder[Camel] = deriveEncoder
  implicit lazy val camelDecoder: Decoder[Camel] = deriveDecoder
}

这是可以的,当测试这一点时:

代码语言:javascript
复制
val camel = Camel(firstName = "Camelbek", lastName = "Camelov", waterPerDay = 30)

private val camelJ = Json.obj(
    "firstName" -> Json.fromString("Camelbek"),
    "lastName" -> Json.fromString("Camelov"),
    "waterPerDay" -> Json.fromInt(30)
)

"Decoder" must "decode camel types" in {
    camelJ.as[Camel] shouldBe Right(camel)
}

但这个测试没有通过:

代码语言:javascript
复制
val camel = Camel(firstName = "Camelbek", lastName = "Camelov", waterPerDay = 30)

private val camelJ = Json.obj(
    "first_name" -> Json.fromString("Camelbek"),
    "last_name" -> Json.fromString("Camelov"),
    "water_per_day" -> Json.fromInt(30)
)

"Decoder" must "decode camel types" in {
    camelJ.as[Camel] shouldBe Right(camel)
}

如何正确配置circe以便能够在蛇的情况下解析带有密钥的json?

我在使用circe版本的0.10.0

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-04-26 12:29:49

解决方案1

Circe从case类实例中获取字段名,并使用游标遍历JSON,尝试获取每个字段名的值,并尝试将其转换为所需的类型。

这意味着你的解码器不能同时处理这两种情况。

解决这个问题的方法是编写两个解码器:

  1. 基本解码器(deriveEncoder将工作)
  2. 编码器,它使用HCursor在JSON中导航并获取蛇案例密钥
代码语言:javascript
复制
val decoderDerived: Decoder[Camel] = deriveDecoder
val decoderCamelSnake: Decoder[Camel] = (c: HCursor) =>
    for {
      firstName <- c.downField("first_name").as[String]
      lastName <- c.downField("last_name").as[String]
      waterPerDay <- c.downField("water_per_day").as[Int]
    } yield {
      Camel(firstName, lastName, waterPerDay)
    }

然后,您可以使用Decoder#or将这两个解码器组合成一个。

代码语言:javascript
复制
implicit val decoder: Decode[Camel] = decoderDerived or decoderCamelSnake

Decoder#or将尝试使用第一个解码器进行解码,如果它失败,那么它将尝试第二个解码器。

解决方案2

如果您只接受camel_case输入,那么您可以使用来自"io.circe" %% "circe-generic-extras" % circeVersion包的@ConfiguredJsonCodec。请注意,要使用此注释,您还需要包括天堂编译器插件。

代码语言:javascript
复制
addCompilerPlugin(
  "org.scalamacros" % "paradise" % "2.1.1" cross CrossVersion.full
)
代码语言:javascript
复制
@ConfiguredJsonCodec
case class User(
  firstName: String,
  lastName: String
)

object User {
  implicit val customConfig: Configuration = Configuration.default.withSnakeCaseMemberNames
}

val userJson = User("John", "Doe").asJson
println(userJson)
// { "first_name" : "John", "last_name" : "Doe" } 

val decodedUser = decode[User](userJson.toString)
println(decodedUser)
// Right(User("John", "Doe"))

另外,请注意,您不需要编写自定义解码器和编码器派生程序,因为该配置为您提供了该功能。

票数 11
EN

Stack Overflow用户

发布于 2021-11-24 02:00:11

另一种无需注释的解决方案:

代码语言:javascript
复制
case class Camel(firstName: String, lastName: String)

object Camel extends AutoDerivation {
  implicit val config: Configuration = Configuration.default.withSnakeCaseMemberNames
  implicit val decoder: Decoder[Camel] = exportDecoder[Camel].instance
  implicit val encoder: Encoder[Camel] = exportEncoder[Camel].instance
}
代码语言:javascript
复制
  val json = Camel("aaa", "bbb").asJson.noSpaces
  val obj  = decode[Camel](json)
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55867077

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档