Question

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?

Was it helpful?

Solution

I'm not sure your searching for data in the right place.

(JsPath \ "name")

lets me think that you're skipping the "data" level in your JSON data structure. You may try to add

(JsPath \ "data" \ "name")

and see if things get better. Moreover, you may try to define your Reads directly defining a implicit format this way :

 Json.format[User]

and then read your data as you're already doing :

val placeResult = request.body.validate[User]

These are just some hints, I'm not a JSON nor a scala expert and I haven't tried the code...

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top