We have an API that always has a total-count and entities in the response, but the entities are of different types. What I'm trying to do is make the parsing & converting to case-classes more generic.
So trying with the following types
case class StandardReturn[A](
`total-count`: Double,
entities: List[A]
)
case class System(
id: String,
name: String
)
And the following example:
object SystemProtocol extends DefaultJsonProtocol {
implicit val systemFormat: RootJsonFormat[System] =
jsonFormat2(System)
implicit def entityFormat[A: JsonFormat] =
jsonFormat(StandardReturn.apply[A], "total-count", "entities")
}
import SystemProtocol._
val response = """{
"total-count": 10,
"entities": [
{ "id": "1", "name": "me" }
]
}"""
class Example {
def transform[A: JsonReader](entityString: String) =
entityString.parseJson
.convertTo[A]
.entities // Where I'm running into trouble
}
object Example {
val transformed = new Example().transform[StandardReturn[System]](response)
}
Example.transformed
Which is understandably giving me
Error:(34, 42) value entities is not a member of type parameter A
entityString.parseJson.convertTo[A].entities // Where I'm running into trouble
^
How would I set up the case classes / types so that transform could be assured that entities will always exist after converting to type A (where A is StandardReturn[A])? I'm not too familiar with scala's type system, thank you for help.
In your Code, the type parameter
Ahas no bounds except the context bound to JsonReader (an implicit parameter of typeJsonReader[A]). Therefore, as you already mentioned,Acould be anything, so you can't call theentitiesmethod. If you convert toStandardReturn[A]instead of justA, this problem is resolved.Additionally, you have to replace the type parameter in
new Example().transform[StandardReturn[System]](response)by justSysteminstead ofStandardReturn[System], as the method above was changed.The compiler now needs an implicit parameter of type
JsonReader[StandardFormat[System]]. But in the implicit scope, there is only thesystemFormatof typeJsonReader[System](inSystemProtocol). The compiler does not give up yet: he tries to find an implicit conversion fromJsonReader[System]toJsonReader[StandardFormat[System]], and that is just the methodentityFormatyou defined. Yeah!One last remark: You could further simplify the method
entityFormatif you replacejsonFormat(StandardReturn.apply[A], "total-count", "entities")byjsonFormat2(StandardReturn.apply[A]), as noted in the documentation.