-
-
Save mminer/5464753 to your computer and use it in GitHub Desktop.
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) |
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.
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.
@pconerly , The problem is that a number/float variables will not work well using your method.
@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)
Also note, that BaseHandler needs to be defined. Instead one can probably use tornado.web.RequestHandler.
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)?
There's a bug in this-- tornado expects the argument dictionary to be in the form of:
Even if there's only one value for each key. This is to handle situations where we can pass multiple key-value pairs with the same key into a url querypath.
So if you post with
{'message':'derp'}
and use the built-in tornado function for getting arguments, you'll get this:This is because tornado always gives you the last argument. -_-;
Additionally I pop the raw json out of the arguments dictionary. In the original version it stays there and it's ugly.
Here's my version of
prepare()
But overall: @mminer this is awesome and thanks for publishing this! As a tornado-noob it helped me a bunch.