【问题标题】:How to parse json list or array in scala for play framework 2.2如何在 scala 中解析 json 列表或数组以进行播放框架 2.2
【发布时间】:2015-01-21 18:55:31
【问题描述】:

我正在编写一些 RESTful API 测试用例,但几乎没有使用 scala playframework 的经验。

这是我的 JSON 示例。

  [ {
   "size" : "5082",
   "date-created" : "Wed Nov 19 17:10:39 CST 2014",
   "id" : "546d236fb84e894eefd8f769",
   "content-type" : "image/png",
   "filename" : "chrome-on-windows.PNG"
 }, {
   "size" : "15684",
   "date-created" : "Mon Jan 12 17:28:02 CST 2015",
   "id" : "54b4588266b3d11b1c1e9db6",
   "content-type" : "image/png",
   "filename" : "logos_ncsa.png"
 }, {
   "size" : "1267871",
   "date-created" : "Mon Jan 12 17:28:03 CST 2015",
   "id" : "54b4588366b3d11b1c1e9dba",
   "content-type" : "image/jpg",
   "filename" : "morrowplots.jpg"
 } ]

如您所见,我有一个 JSON 项目的列表/数组。我想获取“morrowplots.jpg”文件的 id 并将其存储到一个变量中以用于成功的 API 调用。

所以我将代码设置为如下所示。下面代码中的结果变量就是上面看到的 JSON 字符串。

  case class FileName(size: String, datecreated: String, id: String,    contenttype: String, filename: String)

  implicit val fileReads: Reads[FileName] = (
  (__ \\ "size").read[String] and
  (__ \\ "datecreated").read[String] and
  (__ \\ "id").read[String] and
  (__ \\ "content-type").read[String] and
  (__ \\ "filename").read[String]
  )(FileName.apply _)

  val json: JsValue = Json.parse(contentAsString(result))

  val nameResult: JsResult[FileName] = json.validate[FileName](fileReads)
  info("Right after validate")
    nameResult match {
      case s: JsSuccess[FileName] => {
        val testfile: FileName = s.get
        // Do something with testfile
        info("Success")
      }
      case e: JsError => {
        info("Error")
        info("Errors: " + JsError.toFlatJson(e).toString())
      }
    }

这给了我以下错误。

[信息] + 错误: {"objsize":[{"msg":"error.path.result.multiple","args":[]}],"objfilename":[{"msg":" error.path.resul t.multiple","args":[]}],"objid":[{"msg":"error.path.result.multiple","args":[]}],"objcontent-type":[{"msg":"error.path .result.multiple","args":[]}],"obj*datecreated":[{"msg":"error.path.missing","args":[]}]}

那么我该如何解决这个列表/数组问题以及如何通过文件名搜索来获取 id?

提前致谢。

【问题讨论】:

    标签: arrays json scala playframework-2.2


    【解决方案1】:

    首先,您可能决定使用内置的 json 实用程序而不是执行手动解析。

      case class FileName(size: String, datecreated: String, id: String,    contenttype: String, filename: String)
      object FileName {
        implicit val formatFileName = Json.format[FileName]
      }
    

    在那里,您拥有解析基本 json 对象所需的一切。编译器将使用宏 (IIRC) 生成与您手动编写的代码等效的代码。由于您的字段没有外来验证,因此不需要手动编写 Reads 和 Writes 类。

    那么你可以这样读:

        def readString(str: String) = {
          val jsr: JsResult[Seq[FileName]] = Json.parse(str).validate[Seq[FileName]]
          jsr.fold(
            error => {
              ???
            },
            success => {
              ???
            }
          )
        }
    

    jsr 在这里是一个 JsResult。它可以是 JsSuccess 或 JsError。

    还要注意完整的类型。由于您有一个数组作为输入,因此您应该将输出放在一个集合中,例如 Seq。

    你可以弃牌你的 JsResult。 fold 需要两个函数。一种是针对错误情况,它的类型为 Seq[(JsPath, Seq[ValidationError])] => X,其中 X 是函数的返回类型。它向您展示了所有阻止您的 json 转换为 Seq[FileName] 的问题。

    另一个是成功案例。它的类型为 Seq[FileName] => X,与之前的 X 相同。

    您现在可以决定在这两个函数中添加什么。

    正如 Justin 所指出的,您也可以使用匹配来编写它。即使功能较少,它也可能更容易:

        def readString(str: String) = {
          val jsr: JsResult[Seq[FileName]] = Json.parse(str).validate[Seq[FileName]]
          jsr match {
            case JsResult(seq) => ???
            case e: JsError => ???
          }
        } 
    

    【讨论】:

      【解决方案2】:

      我不是 Play 方面的专家,所以这可能不是惯用的,但它应该可以解决您的问题。首先,你的 json 是 date-created 而你的 scala 期待 datecreated。其次,您的Reads 应该只使用一个斜线。接下来,您需要针对List[FileName] 运行validate

      至于文件名搜索,您现在可以从JsSuccess 中提取列表并对其运行filter

      最终的代码如下所示

      case class FileName(size: String, datecreated: String, id: String, contenttype: String, filename: String)
      
        implicit val fileReads: Reads[FileName] = (
        (__ \ "size").read[String] and
        (__ \ "date-created").read[String] and
        (__ \ "id").read[String] and
        (__ \ "content-type").read[String] and
        (__ \ "filename").read[String]
        )(FileName)
      
        val json: JsValue = Json.parse(contentAsString(result))
      
        val nameResult = json.validate[List[FileName]]
      
        val list = nameResult match {
            case JsSuccess(list : List[FileName], _) => list
            case e: JsError => {
              info("Errors: " + JsError.toFlatJson(e).toString())
              List()
            }
          }
      
        list filter(_.filename contains "morrow")
      

      【讨论】:

        猜你喜欢
        • 2014-03-29
        • 2021-10-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-07-11
        • 2019-05-07
        • 2014-05-03
        • 1970-01-01
        相关资源
        最近更新 更多