2012-05-30 21 views
3

我正在嘗試使用PlayFramework編寫乾式CRUD寧靜服務。這是它的代碼。可選的Json身體分析器

def crudUsers(operation: String) = Action(parse.json) { request => 
(request.body).asOpt[User].map { jsonUser => 
    try { 
    DBGlobal.db.withTransaction { 
     val queryResult = operation match { 
     case "create" => 
      UsersTable.forInsert.insertAll(jsonUser) 
      Json.generate(Map("status" -> "Success", "message" -> "Account inserted")) 

     case "update" => 
      val updateQ = UsersTable.where(_.email === jsonUser.email.bind).map(_.forInsert) 
      println(updateQ.selectStatement) 
      updateQ.update(jsonUser) 
      Json.generate(Map("status" -> "Success", "message" -> "Account updated")) 

     case "retrieve" => 
      val retrieveQ = for(r <- UsersTable) yield r 
      println(retrieveQ.selectStatement) 
      Json.generate(retrieveQ.list) 

     case "delete" => 
      val deleteQ = UsersTable.where(_.email === jsonUser.email) 
      deleteQ.delete 
      Json.generate(Map("status" -> "Success", "message" -> "Account deleted")) 
     } 
     Ok(queryResult) 
    } 
    } catch { 
    case _ => 
     val errMsg: String = operation + " error" 
     BadRequest(Json.generate(Map("status" -> "Error", "message" -> errMsg))) 
    } 
}.getOrElse(BadRequest(Json.generate(Map("status" -> "Error", "message" -> "error")))) 

}}

我注意到,更新,刪除和創建業務很好地工作。但是,檢索操作以For request 'GET /1/users' [Invalid Json]失敗。我非常確定這是因爲JSON解析器不能容忍GET請求,而在正文中沒有傳入JSON。

有沒有辦法特殊情況下獲取/檢索操作,而不會失去我開始在這裏乾的方法?

+1

JSON *要求*有一個頂層JSON對象或JSON陣列。 「沒有數據」是無效的JSON。參見[RFC4627](http://www.ietf.org/rfc/rfc4627.txt):'JSON-text = object/array'。 – 2012-05-30 04:15:54

+0

好的。謝謝。看起來替代方案是構建一個更智能的解析器,它只接受獲取請求的文本內容。任何想法我怎麼能做到這一點? –

回答

2

我的猜測是你分裂你的方法,以便你可以創建一個不同的路線,爲有或沒有身體。

即使空字符串被解析爲JSON,代碼的設計似乎也不起作用。 map方法不會被執行,因爲沒有用戶。這會導致匹配操作永遠不會被執行。

更新

既然你提到乾的,我會重構它弄成這個樣子:

type Operations = PartialFunction[String, String] 

    val operations: Operations = { 
    case "retrieve" => 
     println("performing retrieve") 
     "retrieved" 
    case "list" => 
     println("performing list") 
     "listed" 
    } 

    def userOperations(user: User): Operations = { 
    case "create" => 
     println("actual create operation") 
     "created" 
    case "delete" => 
     println("actual delete operation") 
     "updated" 
    case "update" => 
     println("actual update operation") 
     "updated" 
    } 

    def withoutUser(operation: String) = Action { 
    execute(operation, operations andThen successResponse) 
    } 

    def withUser(operation: String) = Action(parse.json) { request => 
    request.body.asOpt[User].map { user => 
     execute(operation, userOperations(user) andThen successResponse) 
    } 
     .getOrElse { 
     errorResponse("invalid user data") 
     } 
    } 

    def execute(operation: String, actualOperation: PartialFunction[String, Result]) = 
    if (actualOperation isDefinedAt operation) { 
     try { 
     DBGlobal.db.withTransaction { 
      actualOperation(operation) 
     } 
     } catch { 
     case _ => errorResponse(operation + " error") 
     } 
    } else { 
     errorResponse(operation + " not found") 
    } 

    val successResponse = createResponse(Ok, "Success", _: String) 
    val errorResponse = createResponse(BadRequest, "Error", _: String) 

    def createResponse(httpStatus: Status, status: String, message: String): Result = 
    httpStatus(Json.toJson(Map("status" -> status, "message" -> message)))