[英]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"
} ]
如您所见,我有一个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] +错误:{“obj size”:[{“msg”:“error.path.result.multiple”,“args”:[]}],“obj filename”:[{“msg”:“error .path.resul t.multiple“,”args“:[]}],”obj id“:[{”msg“:”error.path.result.multiple“,”args“:[]}],”obj content-type“:[{”msg“:”error.path .result.multiple“,”args“:[]}],”obj * datecreated“:[{”msg“:”error.path.missing“, “ARGS”:[]}]}
那么如何修复此List / Array问题以及如何通过filename搜索以获取ID?
提前致谢。
首先,您可能决定使用内置的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 and 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 => ???
}
}
我不是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")
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.