Scala Sealed json4s trait as an enumeration

We have our status, defined as:

sealed trait Status case object Status { case object StatusA extends Status case object StatusB extends Status case object StatusC extends Status } 

Our status is as follows:

 val status = Status.StatusA 

Is there a way (de) to serialize such a structure with predefined json4s fomratters?

We tried with defult formatter, for example:

 implicit val formats = new org.json4s.DefaultFormats 

and it didn’t work. Then we tried to use ext provided by json4s with Enum support:

 implicit val formats = org.json4s.DefaultFormats + new org.json4s.ext.EnumSerializer(Status) 

and he did not work again. We had to completely change the structure of the sealed trait to the actual Enumeration s. Is there a way to do this with case class es?

+5
source share
1 answer

Here is a complete working example, I changed my classes a bit to simplify the example, and this way you can use the "name" in different ways, you can actually omit the "def name", but in this case you will need to change the serializer a bit. The second Serializer is just below.

 sealed trait Status { def name: String } case object Status { def apply(name: String): Status = name match { case StatusA.name => StatusA case StatusB.name => StatusB case StatusC.name => StatusC case _ => throw new UnsupportedOperationException("Unknown value") } } case object StatusA extends Status { override val name = "StatusA" } case object StatusB extends Status { override val name = "StatusB" } case object StatusC extends Status { override val name = "StatusC" } class StatusSerializer extends CustomSerializer[Status](formats => ( { case JString(s) => Status(s) case JNull => throw new UnsupportedOperationException("No status specified") }, { case status: Status => JString(status.name) }) ) case class SimpleRichObject(someString: String, someInt: Int, statuses: List[Status]) object Test extends App { implicit val formats = DefaultFormats + new StatusSerializer val obj = SimpleRichObject("Answer to life the universe and everything", 42, List(StatusA, StatusB, StatusC)) def toCompactJsonString(any: Any) = { JsonMethods.compact(JsonMethods.render(Extraction.decompose(any))) } def toPrettyJsonString(any: Any) = { JsonMethods.pretty(JsonMethods.render(Extraction.decompose(any))) } /** To Json */ println(s"Compact json:\n${toCompactJsonString(obj)}") println(s"Pretty json:\n${toPrettyJsonString(obj)}") /** From Json */ val json = """{ | "someString":"Here is a another String", | "someInt":1234, | "statuses":["StatusA","StatusB"] |}""".stripMargin val richObj = JsonMethods.parse(json).extract[SimpleRichObject] println(s"Rich object toString: $richObj") } 

Here is the second Serializer, using the second, you do not need to define additional code in "Enums"

 class SecondStatusSerializer extends CustomSerializer[Status](formats => ( { case JString(s) => s match { case "StatusA" => StatusA case "StatusB" => StatusB case "StatusC" => StatusC } case JNull => throw new UnsupportedOperationException("No status specified") }, { case status: Status => status match { case StatusA => JString("StatusA") case StatusB => JString("StatusB") case StatusC => JString("StatusC") } }) ) 

And here is what this one looks like at startup, compact json:

 {"someString":"Answer to life the universe and everything","someInt":42,"statuses":["StatusA","StatusB","StatusC"]} 

Pretty json:

 { "someString":"Answer to life the universe and everything", "someInt":42, "statuses":["StatusA","StatusB","StatusC"] } 

Rich object toString: SimpleRichObject (Here's another line, 1234, List (StatusA, StatusB))

0
source

All Articles