Skip to content

Instantly share code, notes, and snippets.

@mminer
Created April 26, 2013 02:36
Show Gist options
  • Save mminer/5464753 to your computer and use it in GitHub Desktop.
Save mminer/5464753 to your computer and use it in GitHub Desktop.
A JSON request handler for Tornado.
import json
import tornado.web
class JsonHandler(BaseHandler):
"""Request handler where requests and responses speak JSON."""
def prepare(self):
# Incorporate request JSON into arguments dictionary.
if self.request.body:
try:
json_data = json.loads(self.request.body)
self.request.arguments.update(json_data)
except ValueError:
message = 'Unable to parse JSON.'
self.send_error(400, message=message) # Bad Request
# Set up response dictionary.
self.response = dict()
def set_default_headers(self):
self.set_header('Content-Type', 'application/json')
def write_error(self, status_code, **kwargs):
if 'message' not in kwargs:
if status_code == 405:
kwargs['message'] = 'Invalid HTTP method.'
else:
kwargs['message'] = 'Unknown error.'
self.response = kwargs
self.write_json()
def write_json(self):
output = json.dumps(self.response)
self.write(output)
@benjaminwilson
Copy link

Thanks for this. I am confused about the pop()? The body shouldn't be a key in the arguments dict. Also the logger fails without an import.

@JohnBrodie
Copy link

In Python 3, you might want to do json_data = tornado.escape.json_decode(self.request.body). self.request.body returns bytes in Python 3, and json.loads will not handle it automatically.

Thanks for the code.

@amitripshtos
Copy link

@pconerly , The problem is that a number/float variables will not work well using your method.

@weaming
Copy link

weaming commented May 30, 2016

@JohnBrodie Help me so much, but still no work on python3

This works for me:

for k,v in self.request.body_arguments.items():
    body_kw[k] = str(v[0], encoding='utf-8')
    if body_kw[k] == 'true':
        body_kw[k] = True
    if body_kw[k] == 'false':
        body_kw[k] = False
print(body_kw)

@root42
Copy link

root42 commented Dec 1, 2017

Also note, that BaseHandler needs to be defined. Instead one can probably use tornado.web.RequestHandler.

@AlexanderSov
Copy link

From documentation: "write() is used for non-template-based output; it accepts strings, bytes, and dictionaries (dicts will be encoded as JSON)." So, may be better send self.response to self.write()?
One moment more is about writing json_data into self.request.arguments. Also like in documentation, may be better write its in self.json_args and use tornado.escape.json_decode(self.request.body) instead json.loads(self.request.body)?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment