2015-01-20 18 views
3

我正在編寫一些RESTful API測試案例,並且沒有與scala playframwork一起工作的經驗。如何在scala中解析json列表或數組以用於播放框架2.2

這是我的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()) 
     } 
    } 

這給了我以下錯誤。

[信息] +錯誤: { 「OBJ 大小」:[{ 「msg」 中: 「error.path.result.multiple」, 「參數」 msgid:[]}], 「OBJ文件名」 :[{「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問題,以及如何通過文件名搜索來獲取id?

在此先感謝。

回答

4

我不是玩家的專家,所以這可能不是慣用的,但它應該可以解決您的問題。首先,你的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") 
4

首先,你可以決定使用內置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。摺疊需要兩個功能。一種是出現錯誤的情況,它的類型是Seq [(JsPath,Seq [ValidationError])] => X,其中X是函數的返回類型。它顯示了所有阻止你的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 => ??? 
     } 
    } 
相關問題