Ensure the POST data is valid JSON
<p>I am developping a JSON API with Python Flask.<br>
What I want is to always return JSON, with a error message indicating any error that occured.</p>

<p>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.</p>

<p>Preferably, I d also like to not force the user to send the <code>Content-Type</code> header, and if <code>raw</code> or <code>text</code> content-type, try to parse the body as JSON nonetheless.</p>

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

<p>I've read about adding decorator to <code>request</code> to do that, but no comprehensive example.</p>

<p>You have three options:</p>

<ul>
<li><p>Register a <a href="http://flask.pocoo.org/docs/0.11/patterns/errorpages/#error-handlers" rel="nofollow">custom error handler</a> for 400 errors on the API views. Have this error return JSON instead of HTML.</p></li>
<li><p>Set the <a href="https://flask.readthedocs.io/en/latest/api/#flask.Request.on_json_loading_failed" rel="nofollow"><code>Request.on_json_loading_failed</code> method</a> to something that raises a <a href="http://werkzeug.pocoo.org/docs/0.11/exceptions/#werkzeug.exceptions.BadRequest" rel="nofollow"><code>BadRequest</code> exception</a> subclass with a JSON payload. See <a href="http://werkzeug.pocoo.org/docs/0.11/exceptions/#custom-errors" rel="nofollow"><em>Custom Errors</em></a> in the Werkzeug exceptions documentation to see how you can create one.</p></li>
<li><p>Put a <code>try: except</code> around the <code>request.get_json()</code> call, catch the <code>BadRequest</code> exception and raise a new exception with a JSON payload.</p></li>
</ul>

<p>Personally, I'd probably go with the second option:</p>

<pre><code>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
</code></pre>

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

python json flask