2016-06-25 36 views
3

我有一個函數,它會通過ajax請求獲取一個令牌。當令牌有效時,它將返回一個響應目錄列表。試圖解析未來響應時出現什麼問題?

def all = Action.async(parse.json) { 
    implicit request => tokenForm.bind(request.body).fold(
    formWithErrors => Future.successful(BadRequest(formWithErrors.toString)), 
    form => checkToken(form.token).map(token => { 
     val directories = Directories.all.map(directory => { 
     Json.toJson(directory) 
     }) 
     Ok(Json.obj("status" -> {if (token.get.id.getOrElse(0) >= 1) true else false}, "message" -> {if (token.get.id.getOrElse(0) >= 1) Json.toJson(directories) else "Invalid token"})) 
    }) 
) 
} 

當我運行上面的代碼它說[作爲^標誌指示的位置發現錯誤]

No Json serializer found for type scala.concurrent.Future[play.api.libs.json.JsValue]. Try to implement an implicit Writes or Format for this type. 
Ok(Json.obj("status" -> {if (token.get.id.getOrElse(0) >= 1) true else false}, "message" -> {if (token.get.id.getOrElse(0) >= 1) Json.toJson(directories) else "Invalid token"})) 
                                      ^
+0

[這](http://stackoverflow.com/questions/31142366/no-json-serializer-as-jsobject-found-for-type-play- api-libs-json-jsobject)可能會有所幫助。 –

+2

'if()true else false'你是真的嗎? :D –

回答

5

這裏是我想出

def all = Action.async(parse.json) { 
    implicit request => tokenForm.bind(request.body).fold(
    formWithErrors => Future.successful(BadRequest(formWithErrors.toString)), 
    form => for { 
     (token, directories) <- checkToken(form.token) zip Directories.all 
    } yield { 
     val isTokenValid = token.isDefined 
     val responseBody = Json.obj(
     "status" -> isTokenValid, 
     "message" -> { 
      if (isTokenValid) 
      Json.toJson(directories) 
      else 
      "Invalid token" 
     } 
    ) 
     Ok(responseBody) 
    } 
) 
} 

asuming checkTokenDirectories.all返回Future。您的功能需要返回Future[Result]。當你摺疊,第一支是正確的

formWithErrors => Future.successful(BadRequest(formWithErrors.toString)) 

然而在第二分支好像你通過調用Directories.all開始了新的未來,你要序列,並返回爲JSON。 Future[JsValue]沒有串行器,因爲這沒有意義,它將不得不阻止獲得結果。你需要以某種方式獲得checkToken(form.token)Directories.all的值。

你可以做到這一點,因爲我上面那樣,或者例如像這樣:

form => { 
    val futureToken = checkToken(form.token) 
    val futureDirectories = Directories.all 

    for { 
    token <- futureToken 
    directories <- futureDirectories 
    } yield { 
    // same code as above 
    } 
} 

請注意,如果你將內聯futureTokenfutureDirectories他們將串行執行。

另請注意,您正在將您的目錄列表轉換爲json兩次。

一旦這裏

val directories = Directories.all.map(directory => { 
    Json.toJson(directory) 
}) 

Asuming Directories.all回報Future[List[Directory]],那麼當你使用map,你通過功能上List[Directory]所以變量應該被命名爲directories沒有directory工作。它將起作用,輕鬆轉換任何可轉換爲json的列表,無需手動執行。

你第二次沒有在這裏

Json.toJson(directories) 
+0

是的你是對的......'checkToken'和'Directories.all'都返回'Future'。 – Johir

+0

感謝您分享您的想法...它適用於我... @Lukasz – Johir

+0

我犯了一個錯誤,條件爲'val isTokenValid = token.get.id.getOrElse(0)> = 1'。它應該是'token.isDefined'而不是'token.get.id.getOrElse(0)> = 1'。它通過一個異常,而我把'token.get.id.getOrElse(0)> = 1'而不是'token.isDefined'。 – Johir