Knows Not Much
Knows Not Much

Reputation: 31546

How to serialize a Scala object to Json which already contains some Json

I have the following object which I am serializing to json using 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)

The output of the statement above is

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

but the output I want is

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

I get the data for the data field from a json based data store. I want to pass it through (so I don't want to unmarshall it into a scala object, only to demarshall it again into json. that marshall/demarshall is a waste of CPU on my server.

So how do I handle such data?

Upvotes: 2

Views: 897

Answers (1)

Mateusz Kubuszok
Mateusz Kubuszok

Reputation: 27535

Well, you can write your own Encoder implementation, e.g.:

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)
  }
}

As a matter of the fact, you have pretty unusual case - one of the fields is a String, that you need to parse, before you put it as a child Json node. Error failure need to be handled somehow - I used empty object, but that isn't necessarily what you would like to use.

If you want to omit the deserialization step... that is not possible. You are building tree of JSON nodes with defined behavior. String cannot suddenly be treated like Json object.

Upvotes: 3

Related Questions