I am trying to process an Ajax POST request in Play Framework 2.1.3. The post data is a JSON object and has a tree structure like:
{ id: "a", name: "myname", kids : [{ id: "a1", name : "kid1", kids: []}, {id: "a2", name: "kid2", kids: [{id: "aa1", name :"grandkid", kids: []}]}]
I would like to nest the 'children' arbitrarily deep. The class I would have in mind is like this (I realize the recursiveness can be problematic):
case class Person {
id: String,
name: String,
kids: Array[Person]
}
The format I would have in mind:
implicit val personFormat:Format[Person] = Json.format[Person]
Play is throwing errors on my Format that I wrote:
type mismatch; found : controllers.Resources.Person required: Array[controllers.Resources.Person]
I am aware that Play has a Tree structure. I couldn't find examples/documentation on how to tie that to JSON reads.
Any help is highly appreciated, thanks
You will need a recursive val, something like:
implicit val jsonReads: Reads[Person] = ((__ \ "id").read[String] and (__ \ "name").read[String] and (__ \ "kids").read[Seq[Person]])(apply _)
(I've changed the collection type from Array to Seq because it's more general and allows you to change your implementation without affecting downline code.)
This is using the syntax documented here.
The only way that I see this working is using either JsArray or Array[String] instead of Array[Person] in your Person case class. The JSON Macro Inception can only generate reads + writes code for primitives and lists, maps, and arrays for objects for which there already exist implicit JSON read + write code. Essentially you can't have a case class that references itself.
package models
import play.api.libs.json._
case class Person(
id : String,
name : String,
kids : JsArray
)
object Person extends ((String,String,JsArray) => Person) {
implicit val jsonFormat = Json.format[Person]
}
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