Десериализация JSON на основе поля в полезной нагрузке в Scala

У меня есть аналогичный вопрос с десериализацией JSON на основе полей в.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
}

Мне нужно десериализовать два вышеупомянутых объекта JSON на основе поля data_type в Scala с помощью Circe библиотека.

Как я могу это сделать?

1 ответ

Решение

Этот фрагмент работает для меня в Аммоните:

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 или аналогичные, но это было бы за рамками этого вопроса.

Другие вопросы по тегам