Search code examples
jsonscalaplayframeworkplayframework-2.0scala-2.10

Traversing multiple JSON arrays in Play/Scala


{
    "location":{
        "residents":[{
            "renting":[{
                "name":"John Doe"
                "pets":"2"
            },{
                "name":"Jane Smith"
                "pets":"2"
            }]
        }]
    }
}

I can successfully traverse location with this -

val json = ...

val rentReads = (__ \ 'location).read[String]

val rentResult = json.validate[String](rentReads)

rentResult match {
  case s: JsSuccess[String] => Ok(s.get)
  case e: JsError => Ok("Errors: " + JsError.toFlatJson(e).toString())
}

Based on the documentation, I should be able to do something like this -

val skillReads = ((__ \ 'location) \ 'residents)(0).read[String]

but it results in the following error -

Errors: {"obj.VariationResultsWrapper.VariationResultSets[0]":[{"msg":"error.path.missing","args":[]}]}

At this point I'm just trying to understand how to return values from "renting" only. Eventually, I would like to map that result to a case class.


Solution

  • If your eventual goal is to parse this into case classes, just define those case classes and let Play do the heavy lifting.

    case class Renting(name: String, pets: String)
    case class Resident(renting: List[Renting])
    case class Location(residents: List[Resident])
    
    implicit val rentingFormat = Json.format[Renting]
    implicit val residentFormat = Json.format[Resident]
    implicit val locationFormat = Json.format[Location]
    
    (json \ "location").validate[Location]
    res1: play.api.libs.json.JsResult[Location] = JsSuccess(Location(List(Resident(List(Renting(John Doe,2), Renting(Jane Smith,2))))),/residents)