Python 3.6: get JSON from aiohttp request

smart picture smart · Sep 12, 2017 · Viewed 8.8k times · Source

I have some application which uses aiohttp.

I sent POST request into approptiate endpoint, e.g.:

POST mysite.com/someendpoind/

with data similar to:

{"param1": "value1", "param2": "value2", ..., "paramn": None}

Then on backend side, I want to add some additional conditional into this request:

data = await request.json()
data["additional_conditional"] = True

But request.json() fails with an error:

[ERROR] Error handling request
Traceback (most recent call last):
File "/usr/local/lib/python3.5/dist-packages/aiohttp/web_protocol.py", line 422, in start
resp = yield from self._request_handler(request)
File "/usr/local/lib/python3.5/dist-packages/aiohttp/web.py", line 306, in _handle
resp = yield from handler(request)
File "/usr/local/lib/python3.5/dist-packages/aiohttp_session/__init__.py", line 129, in middleware
response = yield from handler(request)
File "/opt/bikeamp/auth/__init__.py", line 57, in wrapped
return (yield from f(request, user))
File "<my_module>.py", line 185, in <my_func>
data_json = await request.json()
File "/usr/local/lib/python3.5/dist-packages/aiohttp/web_request.py", line 469, in json
return loads(body)
File "/usr/lib/python3.5/json/__init__.py", line 319, in loads
return _default_decoder.decode(s)
File "/usr/lib/python3.5/json/decoder.py", line 339, in decode
obj, end = self.raw_decode(s, idx=_w(s, 0).end())
File "/usr/lib/python3.5/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)

Then I decided to check somehow what is the content of my request:

await request.read()

b'field1=value1&field2=value2&field3=value3&field4=&field5=&field6='

So, I'm not sure, but the problem may be with empty parameters.

Also, I was trying to get this data via:

data = await request.post()
data["additional_condition"] = True

But this returns MultiDictProxy. Python can't pickle these objects.

Is there any known solutions?

Answer

Vasili Pascal picture Vasili Pascal · Oct 3, 2017

I had the same issue, if post was something like {"email": "[email protected]"} check it with:

  @router('/', methods=['POST', ])
    async def post_request(request):    

        post = await request.post()
        email = post.get('email')   #  because it's MultiDict 
        logging.warning(post)       #  see post details
        logging.warning(email)      #  shows value "[email protected]" 

        json = await request.text() #
        logging.warning(json)       #  shows json if it was ajax post request