【问题标题】:PlayFramework 2.2 - Scala - Read Mixed ArraysPlayFramework 2.2 - Scala - 读取混合数组
【发布时间】:2013-11-12 20:06:40
【问题描述】:

我正在尝试使用读取器/组合器来解析包含混合数据类型的数组,但我不确定如何为这样的东西指定读取器。我有一些这样的 JSON:

{
  "stuff": [1, 2, true, null, "false", "hahaha", 5, "8"]
}

我想将所有这些解析为字符串表示,但是当我尝试使用List[String] 的阅读器时,我得到了解析异常。我想像这样:

 implicit val mixedArrayReader = (
       (__ \ 'not).readNullable[List[JsValueWrapper]].map(opt => opt.map(list =>
             list.map { wrapper : JsValueWrapper =>
                val parsed : String = wrapper match {
                      case b : JsBoolean => if (b.value) "1" else "0"
                      case n : JsNumber  => n.value.toString
                      case s : JsString  => s.value
                      case JsNull        => "null"
                      case u             => u.toString  // unknown
                   }
                parsed
                }
          ))
 )

但是,由于JsValueWrapper 没有读者,我不知道从这里去哪里。非常感谢任何帮助。

谢谢!

【问题讨论】:

    标签: json scala playframework playframework-2.2 playframework-json


    【解决方案1】:

    首先实现一个自定义的 Reads[String],然后使用Reads.list 将其变成List[String] 的阅读器,然后照常使用该阅读器。为了不隐藏 Play 的默认 Reads[String],更愿意显式传递这些特定的阅读器,而不是为它们定义隐式。

    import play.api.libs.json.Reads
    
    val myReader: Reads[String] = Reads[String](value => JsSuccess(value match {
      case b : JsBoolean => if (b.value) "1" else "0"
      case n : JsNumber  => n.value.toString
      case s : JsString  => s.value
      case JsNull        => "null"
      case u             => u.toString  // unknown
    }))
    
    val listReads = Reads.list[String](myReader)
    

    然后,在组合阅读器中,您可以编写如下内容:

    implicit val objReader =
      (__ \ 'not).readNullable(listReads)
    

    【讨论】:

      【解决方案2】:

      thesamet 的解决方案可能是最直接的。我认为如果您使用.readNullable[List[JsValue]],您的解决方案将起作用,JsValue 是所有 Js* 类型的超类型,您永远不需要直接使用的包装器,它的存在只是为了帮助轻松创建 JSON 对象和数组。

      您可以使用的另一个功能更强大、更灵活的解决方案(请注意,此解决方案可以更好地处理错误)是:

      val anyValueAsStringReader =
        implicitly[Reads[BigDecimal]].map(_.toString) or
        implicitly[Reads[String]] or
        implicitly[Reads[Boolean]].map(if (_) "1" else "0") or
        implicitly[Reads[JsValue]].map(_.toString)
      
      val mixedArrayReader = (__ \ 'not).readNullable(Reads.list(anyValueAsStringReader))
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-05-02
        • 2018-06-20
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多