Python Tornado请求JSON

My application accepts data from POST method which I am running through JQuery's AJAX request. I am sending JSON formatted data, but in handler as I accept request and access the data it turns out to be byte string type.

I am using my_body = self.request.body method.

For example, if I am sending {"drzava":"rs","kategorija":"general"} received data looks like b'drzava=rs&kategorija=general'.

Problem is, afterwards I can't use tornado.escape.json_decode(), to make it dictionary. I keep getting the following error:

Traceback (most recent call last):
  File "/home/stefan/.local/lib/python3.6/site-packages/tornado/web.py", line 1697, in _execute
    result = method(*self.path_args, **self.path_kwargs)
  File "main.py", line 164, in post
    telo_json = tornado.escape.json_decode(telo)
  File "/home/stefan/.local/lib/python3.6/site-packages/tornado/escape.py", line 83, in json_decode
    return json.loads(to_basestring(value))
  File "/usr/lib/python3.6/json/__init__.py", line 354, in loads
    return _default_decoder.decode(s)
  File "/usr/lib/python3.6/json/decoder.py", line 339, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "/usr/lib/python3.6/json/decoder.py", line 357, in raw_decode
    raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

I will post the code, if needed.

The data you receive in your Tornado server application depends on how your data is being "packaged" by the client.

You could have application/x-www-form-urlencoded data (seems to be your case above) which you can process in Tornado using get_body_argument:

drzava = self.get_body_argument("drzava", None)
kategorija = self.get_body_argument("kategorija", None)

or you could have application/json (seems to be want you want):

data = tornado.escape.json_decode(self.request.body)

In order to send JSON data from your browser you need to actually send JSON data and specify the content type:

var data = {"drzava":"rs", "kategorija":"general"};
$.ajax({
    url: YOUR_URL,
    type: "POST",
    data: JSON.stringify(data),
    contentType: "application/json",
    ...

EDIT:
In the end the issue was that the HTML page was sending the data using a form and would not actually use the JS code.

UPDATE: Firstly, there was a typo in my .js file, so AJAX requests weren't being sent. Secondly, Tornado was detecting default POST method (not the AJAX's one), so you have to manually override it by saying something like e.preventDefault(); where e is parameter of anonymous function in JQUERY's action. On the other side, in Tornado, result of self.request.body is something like b'{"country":"rs","category":"sports"}' which can be transformed to dictionary using tornado.escape.json_decode(). Many thanks to @Ionut Ticus for constructive suggestions.

So, after bit of investigating and reading docs, I found the following:

HTTPServerRequest.body is now always a byte string (previously the default empty body would be aunicode string on python 3)

This is written it Tornado's official documentation. Tornado Documentation Release 6.0.4 page 183

Hovewer, I found a way around it.

argumenti = self.request.arguments
drzava_val = argumenti['drzava'][0].decode("utf-8")
kategorija_val =  argumenti['kategorija'][0].decode("utf-8")

data = {
            'drzava': drzava_val,
            'kategorija': kategorija_val
        }