I\'m creating Reads
and Writes
for my Java classes to make use of the Play Framework\'s JSON library.
One of my classes has an abst
Since the implementation of ConcreteObj
will work with any implementation of AbstractObj
I guess you could do something like this:
implicit val ConcreteObjReads: Reads[ConcreteObj] =
(JsPath \ "someField").read[AbstractObj].map { x: AbstractObj =>
new ConcreteObj(x)
}
// I don't know the structure of AbstractObj, but this should give you an idea
implicit val AbstractObjReads: Reads[AbstractObj] =
(JsPath \ "field").read[String].map{ s: String =>
new AbstractObject {
val field = s
}
}
Since the concrete type is not available until runtime you will have to type check/parse type at runtime. It is possible you can do it with the functional syntax api but I've resorted to actually implementing Reads/Writes/Format for those cases, something along the lines:
implicit object Example extends Reads[AbstractThing] {
def reads(json: JsValue) = {
// somehow figure out the concrete subclass of AbstractThing
// based on the json
(json \ "type").as[String] match {
case "type1" => Json.fromJson[Concrete1](json)
case "type2" => Json.fromJson[Concrete2](json)
case t => JsError(s"Unknown concrete type of AbstractThing: $t")
}
}
}
This way you can still create re-usable formats/reads/writes for the concrete types that you can use where you do know at compile time what kind of object you are serializing/deserializing.