Edit I initially described this wrong -- rewritten below.
For some reason, I cannot get Angular to send the JSON payload in a way that it is interpreted as a simple string. Looking at the JsObject body, it is always a ListBuffer
for some unknown reason.
Code
Application.scala
(Taking from here)
implicit val userReads: Reads[User] = (
(JsPath \ "name").read[String] and
(JsPath \ "language").read[Int]
)((name: String, languageId: Int) => User(None, name, languageId))
def submitUser = Action(BodyParsers.parse.json) {
implicit request =>
val userResult = request.body.validate[User]
userResult.fold(
errors => {
BadRequest(Json.obj("status" -> "KO", "message" -> JsError.toFlatJson(errors)))
},
user => {
userDao.add(user)
Ok(Json.obj("status" -> "OK", "message" -> ("User '" + user.full_name + "' saved.")))
}
)
}
User.scala
case class User(id: Option[Int], full_name: String, language: Int)
app.js
(Only relevant piece)
$scope.submit = function(event) {
$scope.loadingTracker = promiseTracker();
return $http.post('/user', {
data: {name: 'Joe Blow', language: 1}
}, { tracker: $scope.loadingTracker })
.success(function(id) {
console.log("Success! Created user with id " + id);
});
}
(I have tried using JSON.stringify
, etc.)
Exception
Doing the traditional "Reads" on this gives me this error, or something similar:
play.api.Application$$anon$1: Execution exception[[JsResultException: JsResultException(errors:List((,List(ValidationError(error.expected.jsstring,WrappedArray())))))]]
at play.api.Application$class.handleError(Application.scala:293) ~[play_2.10-2.2.2.jar:2.2.2]
at play.api.DefaultApplication.handleError(Application.scala:399) [play_2.10-2.2.2.jar:2.2.2]
at play.core.server.netty.PlayDefaultUpstreamHandler$$anonfun$2$$anonfun$applyOrElse$3.apply(PlayDefaultUpstreamHandler.scala:261) [play_2.10-2.2.2.jar:2.2.2]
at play.core.server.netty.PlayDefaultUpstreamHandler$$anonfun$2$$anonfun$applyOrElse$3.apply(PlayDefaultUpstreamHandler.scala:261) [play_2.10-2.2.2.jar:2.2.2]
at scala.Option.map(Option.scala:145) [scala-library-2.10.4.jar:na]
at play.core.server.netty.PlayDefaultUpstreamHandler$$anonfun$2.applyOrElse(PlayDefaultUpstreamHandler.scala:261) [play_2.10-2.2.2.jar:2.2.2]
Caused by: play.api.libs.json.JsResultException: JsResultException(errors:List((,List(ValidationError(error.expected.jsstring,WrappedArray())))))
at play.api.libs.json.JsValue$$anonfun$2.apply(JsValue.scala:64) ~[play-json_2.10-2.2.2.jar:2.2.2]
at play.api.libs.json.JsValue$$anonfun$2.apply(JsValue.scala:64) ~[play-json_2.10-2.2.2.jar:2.2.2]
at play.api.libs.json.JsResult$class.fold(JsResult.scala:71) ~[play-json_2.10-2.2.2.jar:2.2.2]
at play.api.libs.json.JsError.fold(JsResult.scala:10) ~[play-json_2.10-2.2.2.jar:2.2.2]
at play.api.libs.json.JsValue$class.as(JsValue.scala:62) ~[play-json_2.10-2.2.2.jar:2.2.2]
at play.api.libs.json.JsObject.as(JsValue.scala:164) ~[play-json_2.10-2.2.2.jar:2.2.2]
Because the data looks like this:
> body = {play.api.libs.json.JsObject@14793} {"data":{"name":"Joe Blow","language":1}}
and "JsObject" has a member fields
which is a ListBuffer (in this case, size = 1)
I know this is a totally "noob" question but I don't know how to read the ListBuffer
from the body, let alone parse it into the case class. I would like to just parse this whatever way is most proper; it makes no sense to me why this simple JSON is being turned into a ListBuffer by Play.
Any suggestions/ideas?