在 Scala 中基于 Payload 中的 Field 反序列化 JSON
Deserialize JSON based on Field in Payload in Scala
我有一个与 Deserialize json based on fields in .Net (C#) 类似的问题,但在 Scala 中进行。
我有一个应用程序在 2 种类型的 json 对象(帐户和用户)中进行流式传输。
帐号:
{
"data_type": "account",
"id": 1,
"type": "Trial",
"created_at": 1523982003,
}
用户:
{
"data_type": "user",
"id": 1,
"account_id": 1,
"department": "Finance"
"created_at": 1523982122
}
我需要在 Circe
库的帮助下基于 Scala
中的字段 data_type
反序列化上述两个 json 对象。
我该怎么做?
这段代码在 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
或类似内容,但这超出了本题的范围。
我有一个与 Deserialize json based on fields in .Net (C#) 类似的问题,但在 Scala 中进行。
我有一个应用程序在 2 种类型的 json 对象(帐户和用户)中进行流式传输。
帐号:
{
"data_type": "account",
"id": 1,
"type": "Trial",
"created_at": 1523982003,
}
用户:
{
"data_type": "user",
"id": 1,
"account_id": 1,
"department": "Finance"
"created_at": 1523982122
}
我需要在 Circe
库的帮助下基于 Scala
中的字段 data_type
反序列化上述两个 json 对象。
我该怎么做?
这段代码在 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
或类似内容,但这超出了本题的范围。