Patrick White
Patrick White

Reputation: 882

Play Framework 2.2 Returns "Invalid JSON" On Copyright Character

I'm running into an issue when submitting JSON (as application/json content type) to a play framework action with body parser parse.json, where the JSON contains a copyright symbol.

The failing JSON is:

{
    "Test": "©"
}

The error message returned is 400, Bad Request [Invalid Json]

I believe this should work, all the JSON validators I've checked say this should be valid JSON. Is there a way to debug / trace what play is crashing on, or does anyone have any ideas? My next step was to HTML encode it on the client side, but I just don't think that should be required, and I'm worried that will cause compatibility issues in the future (since, again, this seems to be valid).

I'm using the following curl command to submit:

curl localhost:9001/index -H "Content-Type:application/json;charset=UTF-8" -d @failingJson.txt

NOTE: I re-tried (for reproducability) copying this directly from the website into a txt file and submitting, same issue. There's a chance this has to do with some unrecognized UTF-8 characters, but is there any way to actually find out WHY Play is crashing?

Also, this is crashing well before it hits my code, it's somewhere in the framework.

Any ideas?

Edit 1:

Actually using Play 2.2, not Play 2.1

Edit 2: Here's basically what the controller looks like:

def addItem() = Action.async(parse.json) { request =>
    //Do Stuff
}

And the route:

POST    /index                      controllers.IndexController.addItem()

Edit 3: And, just to be super clear, this works fine:

{
    "Test": "©"
}

Upvotes: 2

Views: 1415

Answers (2)

Patrick White
Patrick White

Reputation: 882

So, this might be contentions - while I think @estmatic is technically correct, I think there's a bit of gray area here. Since we're exposing a public API, we want to be as permissive as possible. And, I think the Play JSON validator is just too strict. The way we fixed this on our side, which might work for people that have similar issues, is to use the raw body parser and parse at the controller level.

def addItem() = Action.async(parse.raw) { request =>
    val s = new String(request.body.asBytes().get)
    val jsBody = Json.parse(s)
    val jsonResult = Json.fromJson[Entity](jsBody)
    val entity = jsonResult.get
}

Now, the weird part is I suspect that the play framework is using the exact same mechanism internally for json validation, but the above works and handles the weird characters. It sort of "kicks the can" down the road, but was what we were looking for.

Upvotes: 0

estmatic
estmatic

Reputation: 3449

I think the problem is that your failingJson.txt file isn't encoded as UTF-8, which is required for JSON. I was able to reproduce your problem by encoding your sample JSON (with copyright character) as ISO-8859-1. With no changes other than re-saving the file as UTF-8 the same curl request came through fine.

Basically, your app is probably working fine, you just need to make sure your data file is encoded correctly.

Upvotes: 0

Related Questions