0

I recently started to learn Scala. I need an EASY way to SERIALIZE my data in Json. Below I will give an example of data. I tried several popular libraries: GSON, Play JSON, Circe, but did not get the result! GSON does not know how to work with Option (eg Option [String]), in Play JSON and Circe they need to describe serialization and deserialization of an abstract class (I don’t know how to get around this).

// Test data

  abstract class Base(id: Long, descr: Option[String])
  case class A(id: Long, descr: Option[String], a: Option[Long]) extends Base(id, descr)
  case class B(id: Long, descr: Option[String], b: Option[Double]) extends Base(id, descr)

  case class Data(id: Long, user: Option[String], data: Option[Array[Base]])

  val test: Array[Data] = Array(
    Data(1, Some("Qqq"), None),
    Data(2, None, None),
    Data(3, Some("Zzz"), Some(
      Array(
        A(1, Some("a1"), Some(111)),
        A(2, Some("a2"), None),
        A(3, None, Some(333)),
        B(4, Some("b1"), Some(444.444)),
        B(5, Some("b2"), None),
        B(6, None, Some(666.666))
      )
    ))   )

2 Answers2

1

You need to create a companion object for your case class as:

object Data {
  import play.api.libs.json._
  implicit val read = Json.reads[Data]
  implicit val write = Json.writes[Data]
  implicit val dataFormat = Json.format[Data]

  def tupled = (Data.apply _).tupled
}

Both case class and object must be placed in same file.

Then, when you need to use it, import play.api.libs.json._:

   val myObject = new Data(100, None, None)
   val myJson = Json.toJson(myObject)

Obs: this is a Play framework library, if you not use this fw, I'm not sure that you can use it.

Another obs ... when you convert an object into a json, all optional parameters, if are None, will not appear into your json value. So, for my example, result will not contain user and data parameters:

{
   "id": 100
}
AlleXyS
  • 2,476
  • 2
  • 17
  • 37
1

Using circe:

  import cats.syntax.functor._
  import io.circe.{Decoder, Encoder}, io.circe.generic.auto._
  import io.circe.syntax._

  implicit val encodeBase: Encoder[Base] = Encoder.instance {
    case foo @ A(_, _, _) => foo.asJson
    case bar @ B(_, _, _) => bar.asJson
  }

And then you can just do

  test.asJson
mfirry
  • 3,634
  • 1
  • 26
  • 36