2015-01-20 4 views
3

일부 RESTful API 테스트 케이스를 작성하고 있으며 스칼라 플레이 프레임 작업에 대한 경험이 거의 없습니다.재생 프레임 워크 2.2에서 json 목록 또는 스칼라를 스칼라로 구문 분석하는 방법

다음은 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", "인수"[]}, "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": []}]}

이 목록/배열 문제를 어떻게 해결할 수 있으며 파일 이름별로 검색하여 ID를 얻는 방법은 무엇입니까?

미리 감사드립니다.

답변

4

저는 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") 
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 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가 있습니다.

이제 두 가지 기능을 넣을 항목을 결정할 수 있습니다.

저스틴이 지적한 것처럼, 당신은 또한 그것을 가지고 글을 쓸 수 있습니다. 기능이 덜한 경우에도 더 쉬울 수 있습니다.

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