Как сериализовать объект Scala в Json, который уже содержит некоторый Json

У меня есть следующий объект, который я сериализую в JSON с помощью Circe

case class Person(name: String, data: String)
val x = Person("test", s"""{"a": 10, "b":"foo"}""")
import io.circe._, io.circe.generic.auto._, io.circe.parser._, io.circe.syntax._
println(x.asJson)

Результатом вышеприведенного утверждения является

{
  "name" : "test",
  "data" : "{\"a\":10, \"b\":\"foo\"}"
}

но на выходе я хочу

{
    "name": "test",
    "data": {
        "a": 10,
        "b": "foo"
    }
}

Я получаю данные для поля данных из хранилища данных на основе json. Я хочу передать его (поэтому я не хочу разбивать его на объект scala, только чтобы снова демаршировать его в json. Этот маршалл / демаршалл - пустая трата ЦП на моем сервере.

Так как мне обрабатывать такие данные?

1 ответ

Решение

Ну, вы можете написать свой собственный Encoder реализация, например:

import io.circe.{Encoder, Json}
import io.circe.jawn.parse

case class Person(name: String, data: String)

implicit val personEncoder: Encoder[Person] = new Encoder[Person] {
  override def apply(person: Person): Json = {
    val name = Json.fromString(person.name)
    val data = parse(person.data) match {
      case Left(_)      => Json.obj()
      case Right(value) => value
    }
    Json.obj("name" -> name, "data" -> data)
  }
}

На самом деле, у вас довольно необычный случай - одно из полей String, что вам нужно проанализировать, прежде чем вы установите его как дочерний узел Json. Ошибка ошибки должна быть как-то обработана - я использовал пустой объект, но это не обязательно то, что вы хотели бы использовать.

Если вы хотите пропустить этап десериализации... это невозможно. Вы строите дерево узлов JSON с определенным поведением. Строка не может внезапно рассматриваться как Json объект.

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