DrakaSAN DrakaSAN - 11 months ago 80
JSON Question

Ensure the POST data is valid JSON

I am developping a JSON API with Python Flask.

What I want is to always return JSON, with a error message indicating any error that occured.

That API also only accept JSON data in the POST body, but Flask by default return a HTML error 400 if it can't read the data as JSON.

Preferably, I d also like to not force the user to send the

header, and if
content-type, try to parse the body as JSON nonetheless.

In short, I need a way to validate that the POST body's is JSON, and handle the error myself.

I've read about adding decorator to
to do that, but no comprehensive example.

Answer Source

You have three options:

  • Register a custom error handler for 400 errors on the API views. Have this error return JSON instead of HTML.

  • Set the Request.on_json_loading_failed method to something that raises a BadRequest exception subclass with a JSON payload. See Custom Errors in the Werkzeug exceptions documentation to see how you can create one.

  • Put a try: except around the request.get_json() call, catch the BadRequest exception and raise a new exception with a JSON payload.

Personally, I'd probably go with the second option:

from werkzeug.exceptions import BadRequest
from flask import json, Request, _request_ctx_stack

def JSONBadRequest(BadRequest):
    def get_body(self, environ=None):
        """Get the JSON body."""
        return json.dumps({
            'code':         self.code,
            'name':         self.name,
            'description':  self.description,

    def get_headers(self, environ=None):
        """Get a list of headers."""
        return [('Content-Type', 'application/json')]

def on_json_loading_failed(self):
    ctx = _request_ctx_stack.top
    if ctx is not None and ctx.app.config.get('DEBUG', False):
        raise JSONBadRequest('Failed to decode JSON object: {0}'.format(e))
    raise JSONBadRequest()

Request.on_json_loading_failed = on_json_loading_failed

Now, every time request.get_json() fails, it'll call your custom on_json_loading_failed method and raise an exception with a JSON payload rather than a HTML payload.