DrMonkey68
DrMonkey68

Reputation: 127

Parsing a list of named JSON objects with Play

I have this JSON from an external API which I don't have any control over that contains an undefined number of named child objets, like so:

{
  // ...
  "promotions": {
    "5": {
      "id": 5,
      "name": "Promo",
      "translations": {
        "fr": "Promo2",
        "de": "Promo2",
        // ...
      }
    },
    "6": {
      "id": 6,
      "name": "Promo2",
      "translations": {
        "fr": "Promo2",
        "de": "Promo2",
        // ...
      }
    },
    // ...
  }
}    

I wish to convert the content of promotions into a list of Promotion objects using the Play JSON library (with the Reads combinators) but I cannot figure out how to approach this.

Upvotes: 0

Views: 108

Answers (2)

andrey.ladniy
andrey.ladniy

Reputation: 1674

If don't need ids in json key you can use values: Iterable[JsValue] of JsObject. So:

  1. For convert to Json with array you may use transformer

    (__ \ "promotions").json.update(
      __.read[JsObject].map(_.values.toList).map(JsArray)
    )
    

    result will be:

    scala> res28: play.api.libs.json.JsResult[play.api.libs.json.JsObject] = JsSuccess({"promotions":[{"id":5,"name":"Promo","translations":{"fr":"Promo2","de":"Promo2"}},{"id":6,"name":"Promo2","translations":{"fr":"Promo2","de":"Promo2"}}]},/promotions)
    
  2. For List[Promotion] (you must have implicit Promotion reader, for example using macros implicit val PromotionRead = Json.reads[Promotion] or you can use own explicit reader as parameter for as[Promotion]), your reader will be:

    (__ \ "promotions").read[JsObject].map(_.values.toList.map(_.as[Promotion]))
    

    with result (for case class Promotion(id: Long, name: String)):

    scala> res40: play.api.libs.json.JsResult[List[Promotion]] = JsSuccess(List(Promotion(5,Promo), Promotion(6,Promo2)),/promotions)
    

Upvotes: 1

tryx
tryx

Reputation: 995

Sounds like you will need to write a custom instance of Reads[Seq[Promotion]]. You can use the reader macro to create Reads[Promotion] and then use that inside a custom implementation that traverses the json tree manually and iterates through your promotion numbering.

Upvotes: 0

Related Questions