How to serialize object to AST using json4s?
Asked Answered
T

1

14

I am writing a Customer Serializer. In that Serializer I would like to somehow say: "and this thing you already know how to serialize".

My current approach looks like that:

    import org.json4s.native.Serialization._
    import org.json4s.JsonDSL.WithBigDecimal._

    object WindowSerializer extends CustomSerializer[Window](format =>
      ( [omitted],
        {
          case Window(frame, size) =>

            ( "size" -> size ) ~
            ( "frame" -> parse(write(frame)) )
        }))

That parse(write(frame)) things is both ugly and inefficient. How to fix that?

Tiedeman answered 10/4, 2014 at 15:31 Comment(0)
C
24

You can call Extraction.decompose(a: Any)(implicit formats: Formats): JValue which produces a JValue from some value using runtime reflection.

import org.json4s._
import org.json4s.jackson.JsonMethods._
import org.json4s.JsonDSL._
import java.util.UUID

case class Thing(name: String)
case class Box(id: String, thing: Thing)

class BoxSerializer extends CustomSerializer[Box](format => ({
  case jv: JValue =>
    val id = (jv \ "id").extract[String]
    val thing = (jv \ "thing").extract[Thing]
    Box(id, thing)
}, {
  case b: Box =>
    ("token" -> UUID.randomUUID().toString()) ~
      ("id" -> box.id) ~
      ("thing" -> Extraction.decompose(box.thing))
}))

implicit val formats = DefaultFormats + new BoxSerializer

val box = Box("1000", Thing("a thing"))

// decompose the value to JSON 
val json = Extraction.decompose(box)
println(pretty(json))
//  {
//    "token" : "d9bd49dc-11b4-4380-ab10-f6df005a384c",
//    "id" : "1000",
//    "thing" : {
//      "name" : "a thing"
//    }
//  }

// and read a value of type Box back from the JSON
println(json.extract[Box])
// Box(1000,Thing(a thing))
Contemptible answered 12/4, 2014 at 23:39 Comment(5)
Great that works! I'll accept this answer if you include only my example modified so that Extraction.decompose is used.Tiedeman
Could you add your Window class to your question?Contemptible
Who cares what Window class is?Tiedeman
I think you care for it, or?Contemptible
note that since decompose reflects on the constructors, you need to ensure that non-case classes have a fully specified constructor, with parameter names corresponding to your field names.Agustin

© 2022 - 2024 — McMap. All rights reserved.