2014-04-17 20 views
0

我的課程列表從coursera api將文檔轉換與播放的Json

{"elements":[ 
    {"id":69, 
    "shortName":"contraception", 
    "name":"Contraception: Choices, Culture and Consequences", 
    "links":{} 
    }, 
    ... 
] 
} 

我想將其轉換爲一個文件,看起來像這樣(我用< --- arrrows爲註釋):

{"Courses":[ 
    { 
     "Type" : "Course", 
     "Title" : "contraception" <---- short name 
     "Content" : {"id":69,  <---- the original course 
      "shortName":"contraception", 
      "name":"Contraception: Choices, Culture and Consequences", 
      "links":{} 
      } 
    }, 
    ... 
]} 

是否有可能使用json來執行此操作? 這裏是我如何做它目前(與轉換爲Scala列表)。

val courses = (response.json \ "elements") 
     .as[List[JsValue]] 
     .map { course => 
     // This is how we want our document to look 
     Json.obj(
     "Type" -> "Course", 
     "Provider" -> "Coursera", 
     "Title" -> (course \ "name"), 
     "Content" -> course 
    ) 
    } 
// then put this into the final json object with "Courses" ... 

回答

2

這可以用Json Transformers API做到:

這是比較凌亂,但是這是接近我:

val json = Json.parse(""" 
    { "elements":[ 
      {"id":69, 
      "shortName":"contraception", 
      "name":"Contraception: Choices, Culture and Consequences", 
      "links":{} 
      }, 
      {"id":100, 
      "shortName":"test", 
      "name":"Test of name", 
      "links":{} 
      } 
     ] 
    } 
         """) 

// Maps single course to app course 
val apiCourseToAppCourse = (
    (__ \ 'Type).json.put(JsString("Course")) and 
    (__ \ 'Title).json.copyFrom((__ \ 'shortName).json.pick) and 
    (__ \ 'Content).json.copyFrom(__.json.pickBranch) 
).reduce 

// Maps an array of elements to an array of courses 
val apiCoursesToAppCourses = of[JsArray].map { 
    case JsArray(arr) => 
    // Map elements to courses 
    JsArray(arr.map { 
     case course: JsObject => 
     apiCourseToAppCourse.reads(course).getOrElse(JsString("Failed to read the course")) 
    }) 

} 

// Maps the API result to a valid result 
val apiToCourses = (__ \ 'Courses).json.copyFrom((__ \ 'elements).json.pick(apiCoursesToAppCourses)) 

// Validate JSON and send result 
json.transform(apiToCourses) match { 
    case JsSuccess(success, p) => 
    Ok(Json.toJson(success)) 
    case JsError(errors) => 
    Ok(errors + "") 
} 

您可以複製代碼,並把它放在一個控制器,I讓它工作。我不太喜歡數組映射,但這是它在文檔示例中完成的方式。

+0

謝謝,哇,這看起來很複雜...我想我可能會保持我的方式:-) [JsArray] .map'的''又做了什麼? – drozzy

+0

這只是創建一個基本的Reads [JsArray]將JsValues數組轉換爲一系列的課程 – dribba