Skip to content

Instantly share code, notes, and snippets.

@ubourdon
Created April 4, 2013 14:57
Show Gist options
  • Save ubourdon/5311085 to your computer and use it in GitHub Desktop.
Save ubourdon/5311085 to your computer and use it in GitHub Desktop.
Comment lire un array json hétérogène avec l'api json de Play! 2.1
implicit val venueReader: Reads[Venue] = (
(__ \ "address").readNullable[String] and
(__ \ "address_2").readNullable[String] and
(__ \ "city").readNullable[String] and
(__ \ "region").readNullable[String] and
(__ \ "country").readNullable[String] and
(__ \ "postal_code").readNullable[String]
)(Venue)
implicit val eventbriteEventReader: Reads[EventbriteEvent] =
(__ \ "event").read(
(__ \ "id").readNullable[Long] and
(__ \ "title").readNullable[String] and
(__ \ "start_date").readNullable[String] and
(__ \ "description").readNullable[String] and
(__ \ "end_date").readNullable[String] and
(__ \ "tags").readNullable[String] and
(__ \ "timezone_offset").readNullable[String] and
(__ \ "url").readNullable[String] and
(__ \ "venue").readNullable[Venue]
tupled
).map( event => EventbriteEvent(event._1.map(_.toString), event._2,event._3,event._4,event._5,event._6,event._7,event._8,event._9) )
val json = """{ "events": [
{
"summary": {
"total_items": 41
}
},
{
"event":{
"id":4819205373
}
}
] }"""
// je cherche le reader qui me permettra de récupérer que les event et pas les summary
val s: Reads[Seq[EventbriteEvent]] = ???
@mandubian
Copy link

On a encore certaines limitations avec les Reads car l'API peut encore progresser et en particulier ce cas où la variable est la clé JSON et pas la valeur: les JsPath sont statiques donc tu ne peux encore utiliser la clé comme variable... Peut-être plus tard!

pour le moment, je pense que le mieux est de faire un Reads custom (d'autres outils sympas devraient arriver mais c'est en gestation ;) )

Voici du code non compilé parce que je suis en vacances donc c'est juste un exo de vacances :)

// déjà tu lis tous les event dans tes events
val eventsReader = Reads[List[JsValue]]{ js => JsSuccess((__ \ "events" \\ "event")(js)) }

// Ensuite tu vas transformer en Reads[List[EventbriteEvent]] en mixant un Reads.map et un List.foldLeft
val finalReader = eventsReader.map{ (l: List[JsValue]) => 
    l.foldLeft( JsSuccess(Seq()): JsResult[Seq[EventbriteEvent]] ){ (res, jsvalue) =>
      val jsr: JsResult[EventbriteEvent] = Json.fromJson[EventbriteEvent](jsvalue)
      for{ 
        seq <- res
        evt <- jsr
      } yield( seq :+ evt )
  }
}

This code might not be perfect in terms of error management but anyway this is a draft :D

Have fun ;)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment