I have this:
sealed trait Block
sealed case class Header(param1: String,
param2: String,
...) extends Block
...
(more sealed case classes that follows the same pattern)
Later, i'm grouping this blocks in a Seq, as follows:
val blocks: Seq[Block with Product with Serializable] = Seq(structure.header, structure.body, ...)
And i want to serialize every block as Json (with Play). I'm doing it as follows:
blocks.map{
x =>
serializeBlock(x)
}
Definition of "serializeBlock":
def serializeBlock[A<:Block](block:A): String = {
block match {
case block: Header => Json.toJson(block).toString()
case block: Body => Json.toJson(block).toString()
... n-times for every possible case class that mixes the block trait
}
}
I have readers and writers for every concrete block (header, body...) but, as you see, when i mix these blocks in a Seq Scala treats it as generic type Block, for this reason i'm doing the pattern matching with every possible block type (implicit casting?). If i simply call "Json.toJson" in the Map Play complains about not finding a Reader/Writer for "block" type.
A "Block" is a fragment of a relatively big JSON. I'm getting the JSON, i'm splitting it in qualified "blocks" and then i'm saving it as a String in a Database:
"Big" JSON:
{
"header" : {
"param1" : "",
...
},
"body" : {
"param1" : "",
...
}
...
}
Blocks
{
"param1" : "",
...
}
My question is: Is there any way to do the serialization without repeating n-times the "block: type" pattern? I mean: is there any way to get the concrete type of that block (knowing that the Seq is typed as superclass "block" and not as the "concrete" type of that block)?
EDIT
I have a Reader/Writer for every block as follows:
implicit val headerReader: Reads[Header] = (
(JsPath \ "param1").read[String] and
(JsPath \ "param2").read[String] and
...
)(Header.apply _)
implicit val headerWriter: Writes[Header] = (
(JsPath \ "param1").write[String] and
(JsPath \ "param2").write[String] and
...
)(unlift(Header.unapply))
EDIT 2:
Is Shapeless a way to solve this?
EDIT 3:
As Andrzej Jozwik noted: "param1" and "param2" are 'wildcard' params that i've used to define my JSON Structure here. Every block has different params.