如何在 scala 中为 play framework 2.2 解析 json 列表或数组

How to parse json list or array in scala for play framework 2.2

我正在编写一些 RESTful API 测试用例,并且对使用 scala playframwork 的经验很少。

这是我的例子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"
 } ]

如您所见,我有 list/Array 个 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())
      }
    }

这给了我以下错误。

[info] + Errors: {"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":[]}]}

那么如何解决这个 List/Array 问题以及如何通过文件名搜索以获取 ID?

提前致谢。

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

关于文件名搜索,您现在可以从 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")

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

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

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

那你可以这样读:

    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 是函数的 return 类型。它向您展示了所有阻止您的 json 被翻译成 Seq[FileName].

的问题

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

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

正如贾斯汀所指出的,你也可以用火柴来写。它可能更容易,即使功能较少:

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