score:0
I have a systematic solution for the problem of serializing sum-types in my json pickling library Prickle. Similar ideas could be employed with Play. There is still some config code required, but its high signal/noise, eg final code like:
implicit val fruitPickler = CompositePickler[Fruit].concreteType[Apple].concreteType[Lemon]
CompositePicklers associated with a supertype are configured with one PicklerPair
for each known subtype (ie sum type option). The associations are setup at configure time.
During pickling a descriptor is emitted into the json stream describing which subtype the record is.
During unpickling, the descriptor is read out of the json and then used to locate the appropriate Unpickler
for the subtype
score:0
An example updated for play 2.5:
object TestContact extends App {
sealed trait Shape
object Shape {
val rectFormat = Json.format[Rect]
val circleFormat = Json.format[Circle]
implicit object ShapeFormat extends Format[Shape] {
override def writes(shape: Shape): JsValue = shape match {
case rect: Rect =>
Json.obj("Shape" ->
Json.obj("Rect" ->
Json.toJson(rect)(rectFormat)))
case circle: Circle =>
Json.obj("Shape" ->
Json.obj("Circle" ->
Json.toJson(circle)(circleFormat)))
}
override def reads(json: JsValue): JsResult[Shape] = {
json \ "Shape" \ "Rect" match {
case JsDefined(rectJson) => rectJson.validate[Rect](rectFormat)
case _ => json \ "Shape" \ "Circle" match {
case JsDefined(circleJson) => circleJson.validate[Circle](circleFormat)
case _ => JsError("Not a valide Shape object.")
}
}
}
}
}
case class Rect(width: Double, height: Double) extends Shape
case class Circle(radius: Double) extends Shape
val circle = Circle(2.1)
println(Json.toJson(circle))
val rect = Rect(1.3, 8.9)
println(Json.toJson(rect))
var json = Json.obj("Shape" -> Json.obj("Circle" -> Json.obj("radius" -> 4.13)))
println(json.validate[Shape])
json =
Json.obj("Shape" ->
Json.obj("Rect" ->
Json.obj("width" -> 23.1, "height" -> 34.7)))
println(json.validate[Shape])
}
score:1
I think that is about as simple as you can make it, if you want to avoid writing the code for each explicit subtype maybe you could do it with reflection, use jackson directly or some other json library with reflection support. Or write your own macro to generate the Format from a list of subtypes.
Source: stackoverflow.com
Related Query
- Json Serialization for Trait with Multiple Case Classes (Sum Types) in Scala's Play
- Case classes for formatting json - with and without the object id
- Play JSON formatter for case class with generic type classes
- How to use Avro serialization for scala case classes with Flink 1.7?
- json deserializer with support for parameterized Case Classes
- Play JSON Reads/Writes with single-parameter case classes
- How to write a Play JSON writes converter for a case class with a single nullable member
- Scala: Copying case classes with trait
- Play json merge formats for case class with more than 22 fields
- Deserializing JSON into user-defined case classes with Jerkson
- Create common trait for all case classes supporting copy(id=newId) method
- Deriving type class instances for case classes with exactly one field
- Mocking case classes with primitive types
- Custom json serialization of structured scala case classes
- Circe Decode to sealed trait extended by multiple case classes
- How can I get random data generated for scala case classes with the ability to "change some values" for unit testing?
- How does serialization work for case classes and compared to java?
- scala circe encoders/decoders for an abstract class with case classes
- trait with only case objects custom implementation in spray json
- Scala semantics of equals/hashCode for case classes with traits
- Parsing more than 22 fields with Spray Json without nesting case classes
- Best practice for defining multiple traits that add behaviour to classes that implement a particular trait
- How to send Json from client with missing fields for its corresponding Case Class after using Json.format function
- Json4s support for case class with trait mixin
- Single function to construct multiple case classes with same structure
- Pattern matching for case classes derived from same trait
- JSON response with Http AKKA and case classes
- Case classes - Copy multiple fields with transforms
- Play: validate JSON with a field with possible multiple types
- How to write a symmetric Play Json formatter for a case class with one field in scala?
More Query from same tag
- Error using spray-aws to connect to DynamoDB under spray framework
- Finding mutual friends for a huge dataset
- ExecutionContext to use with mapAsync in Akka-Streams
- Scala splat operator for only part of parameter list
- Akka - use actorSelection with ask pattern
- Is there an efficiency penalty when using Scala inner functions within non-tail recursive functions?
- Custom ETag algorithm for asset fingerprinting
- Scala-redis subscribes to * but receives zero messages
- Scala/Akka: Run code after an actor doesn't receive a message for a given timeout
- Toomany DOM updates
- Can't figure out syntax in scala compose function
- Spark nested complex dataframe
- Type checker phases
- Why arity-1 syntax in scala does not compile for self invocation?
- Hourly Aggregation in Scala Spark
- Compile and run dotty code using doc command
- scala-way for managing object pools
- Giving a prefix on import to all classes of a given package in Scala
- scala slick or and query
- scala coalesces multiple function call parameters into a Tuple -- can this be disabled?
- Scala - unit testing a Column type function
- Error converting Play Silhouette Module from Guice To Macwire
- Spark get a column as sequence for usage in zeppelin select form
- Is there a Sonar-level code coverage equivalent for Scala?
- How to convert list of list to simple list by removing duplicate values using scala?
- Idiomatic way of extracting lists from a list of tuples
- How to pass a 2 dimensional string array from java code to scala.html in play framework?
- Scala lazy val caching
- How add "jdbc" plug-in with gradle
- Future with Timeout in Scala