使用Play解析命名的JSON对象列表

时间:2016-03-15 21:23:00

标签: json scala parsing playframework playframework-2.0

我有一个来自外部API的JSON,我没有任何控制权,包含一个未定义数量的命名子对象,如下所示:

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

我希望使用Play JSON库(使用Reads组合器)将promotions的内容转换为Promotion个对象列表,但我无法弄清楚如何处理此问题。

2 个答案:

答案 0 :(得分:1)

如果您不需要json密钥中的ID,则可以使用values: Iterable[JsValue] JsObject。所以:

  1. 要使用数组转换为Json,您可以使用变换器

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

    结果将是:

    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. 对于List[Promotion](您必须拥有隐式Promotion阅读器,例如使用宏implicit val PromotionRead = Json.reads[Promotion],或者您可以使用自己的显式阅读器作为as[Promotion]的参数,你的读者将是:

    (__ \ "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)
    

答案 1 :(得分:0)

听起来您需要编写Reads[Seq[Promotion]]的自定义实例。您可以使用reader宏来创建Reads[Promotion],然后在手动遍历json树的自定义实现中使用它,并遍历您的促销编号。