I am using Play framework 2.1 and Scala 2.10.1 and would like to build a general function to construct a JsArray out of a List of custom case class.
private def buildJsArray[T](l: List[T])(result: JsArray): JsArray = {
l match {
case List() => result
case x::xs => buildJsArray(xs)(result :+ Json.toJson(x)) // compiling error here!
}
}
usage:
val applyJsonArray = buildJsArray(List[Apple])(new JsArray())
However, a compiling error is thrown:
No Json deserializer found for type T. Try to implement an implicit Writes or Format for this type.
I do have a Json deserializer written for the particular case class(i.e., Apple case class).
How do I defer the compiler to check the type of x in runtime rather than in compile time?
Many Thanks!
How to fix a error
You have to add an implicit parameter to your method like this:
def buildJsArray[T](l: List[T])(result: JsArray)(implicit tjs: Writes[T]): JsArray
There is such parameter in the Json.toJson
method.
The reason why you have to add this parameter is that you know how to convert T
to json
only when you know what T
is. It means you have the method to serialize T
only when you call buildJsArray
and this parameter allows you to pass this serialization method to the method buildJsArray
.
How to build a JSArray
You could just use a constructor of JsArray
. It takes a Seq[JsValue]
:
new JsArray(l.map{Json.toJson(_)})
There is already an implicit Writes
for Traversable
so you don't need your own method buildJsArray
, you could just use method Json.toJson
with parameter of type List[T]
.
Addition
You should take a look at the collections api. It allows you to write more readable and shorter code:
def buildJsArray[T](l: List[T])(implicit tjs: Writes[T]): JsArray =
l.foldLeft(new JsArray){ (r, x) => r :+ Json.toJson(x) }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With