基于Scala中的Payload中的Field反序列化JSON

时间:2018-04-17 16:21:32

标签: json scala circe

我与Deserialize json based on fields in .Net (C#)有类似的问题,但是在Scala中也是如此。

我有一个应用程序,它有两种类型的json对象(帐户和用户)。

帐户:

{
  "data_type": "account",
  "id": 1,
  "type": "Trial",
  "created_at": 1523982003,
}

用户:

{
  "data_type": "user",
  "id": 1,
  "account_id": 1,
  "department": "Finance"
  "created_at": 1523982122
}

我需要在data_type库的帮助下,根据Scala中的字段Circe反序列化上面的两个json对象。

我该怎么做?

1 个答案:

答案 0 :(得分:1)

这个片段在Ammonite中适用于我:

import $ivy.`io.circe:circe-core_2.12:0.9.3`, io.circe._
import $ivy.`io.circe:circe-generic_2.12:0.9.3`, io.circe.generic._
import $ivy.`io.circe:circe-generic-extras_2.12:0.9.3`, io.circe.generic.extras._
interp.load.plugin.ivy("org.scalamacros" % "paradise_2.12.4" % "2.1.1")

implicit val config: Configuration = Configuration.
  default.
  withSnakeCaseMemberNames.
  withDiscriminator("data_type").
  copy(transformConstructorNames = _.toLowerCase)

{
@ConfiguredJsonCodec
sealed trait InputEntity
object InputEntity {
  @ConfiguredJsonCodec case class Account(id: Long, `type`: String, createdAt: Long) extends InputEntity
  @ConfiguredJsonCodec case class User(id: Long, accountId: Long, department: String, createdAt: Long) extends InputEntity
}
} 

import $ivy.`io.circe:circe-parser_2.12:0.9.3`, io.circe.parser._


val accountJson = """
{
  "data_type": "account",
  "id": 1,
  "type": "Trial",
  "created_at": 1523982003
}
"""
val account = decode[InputEntity](accountJson)
// account: Either[Error, InputEntity] = Right(Account(1L, "Trial", 1523982003L)

val userJson = """
{
  "data_type": "user",
  "id": 1,
  "account_id": 1,
  "department": "Finance",
  "created_at": 1523982122
}
"""
val user = decode[InputEntity](userJson)
// user: Either[Error, InputEntity] = Right(User(1L, 1L, "Finance", 1523982122L))

(顺便说一下:你的JSON示例中有语法错误会导致解析器失败,所以我在上面的代码中修复了它们。)

这里最重要的是

    来自Configuration
  • io.circe.generic.extras._定义了鉴别字段,
  • 将类保持为总和类型,
  • 如果您使用注释生成编解码器,请将@JsonCodec替换为@ConfiguredJsonCodec

实际上,您也可以使用枚举替换这些String,并将createdAt视为LocalDateTime或类似内容,但这不属于此问题的范围。