播放JSON JsPath条件类型

时间:2016-12-01 10:56:36

标签: scala playframework deserialization play-json

我收到来自我无法控制的上游服务器的JSON响应,以进行修改。

JSON可以采用以下格式

{"data":[["Some_text","boolean",["key_string1","key_string2"]]]}

或者它也可以显示为

{"data":[["Some_text","boolean","key_string2"]]}

或者它可能会显示为两者的组合。

{"data":[["Some_text","boolean",["key_string1","key_string2"]],["Some_text","boolean","key_string2"]]}

单独我可以为每种格式定义READS,如果它们不混合的话。 但是,鉴于数据可能是混合格式,我无法理解如何编写Reads以便在转换之前检查底层类型是字符串还是数组?

是否有可能说出类似

的内容
  (
    (JsPath)(0).read[String] and
    (JsPath)(1).read[Boolean] and
    (JsPath)(2).read( **if type is simple, String OR if type is array, then seq** )
  )(SomeGloriousCaseClass)

如何解决反序列化问题?

1 个答案:

答案 0 :(得分:1)

为了好玩,我实施了一个解决方案。您可能需要稍微调整一下:

private def toSeq(jsValue: JsValue): JsResult[Seq[String]] = {
    jsValue match {
      case JsArray(es:Seq[JsValue]) ⇒ sequence(es.map(e ⇒ toSeq(jsValue))).map(_.flatten)
      case JsString(s) ⇒ JsSuccess(s :: Nil)
      case _ ⇒ JsError("INVALID")
    }
  }

  private def sequence[A](seq:Seq[JsResult[A]]):JsResult[Seq[A]] = {
    seq.foldLeft(JsResult.applicativeJsResult.pure(Seq[A]()))((acc, next) ⇒ for(acc2 ← acc; next2 ← next) yield acc2 :+ next2)
  }

希望它有所帮助,并且很乐意在必要时提供进一步的解释。