Mnemosyne Mnemosyne - 6 months ago 33
JSON Question

Error uploading json file to a Cassandra DB through a Play application

I want to upload a json file to my cassandra DB by using a Play application/api.

My html view looks like this.

@main("Welcome to Play") {

<h1> Upload a JSON file </h1>
@helper.form(action = routes.Application.upload, 'enctype -> "text/json") {

<input type="file" name="jsonFile">
<p>
<input type="submit" value="Upload">
</p>

}}


I defined my upload method in the controller:

def upload = Action(parse.json) { request =>
val data = Json.arr(request.body)
sc.parallelize(Seq(data)).saveToCassandra("person", "user", SomeColumns("name", "age"))
Redirect("/index") }


The error message I get is

Bad Request: For request 'POST /upload' [Expecting text/json or application/json body]


Tried with enctype "application/json" as well and there was no difference.
If I try to print the content out I get Null.

The format of my file.json is:

{ "name": "alice", "age": 22}
{ "name": "bob", "age": 23}


Basically I can't seem to properly extract the content from the file.

Answer

See this section of the docs, about request body parsers:

https://www.playframework.com/documentation/2.5.x/ScalaBodyParsers#Choosing-an-explicit-body-parser

Basically, parse.json requires that you made a request with Content-Type of application/json. From the docs:

The json body parser will validate that the request has a Content-Type of application/json, and send back a 415 Unsupported Media Type response if the request doesn’t meet that expectation. Hence we don’t need to check again in our action code.

There is also another body parser that does not have this requirement. Again, from the docs:

This of course means that clients have to be well behaved, sending the correct Content-Type headers with their requests. If you want to be a little more relaxed, you can instead use tolerantJson, which will ignore the Content-Type and try to parse the body as json regardless:

def save = Action(parse.tolerantJson) { request =>
   Ok("Got: " + (request.body \ "name").as[String])
}

So, you have two options here:

  1. Use parse.json and set Content-Type to application/json
  2. Use parse.tolerantJson

Besides that, you JSON file is not valid if the content is like this:

{ "name": "alice", "age": 22} 
{ "name": "bob", "age": 23}

You can check it using JSONLint and I also recommend you to read the definition at json.org. You probably want to have a array like this:

[
  { "name": "alice", "age": 22},
  { "name": "bob", "age": 23}
]

After correct the format, you can either use parse.json or parse.tolerantJson.