Audunfr
Audunfr

Reputation: 37

Falcon parsing json error

I'm trying out Falcon for a small api project. Unfortunate i'm stuck on the json parsing stuff and code from the documentation examples does not work.

I have tried so many things i've found on Stack and Google but no changes. I've tried the following codes that results in the errors below

import json
import falcon

class JSON_Middleware(object):
    def process_request(self, req, resp):
       raw_json = json.loads(req.stream.read().decode('UTF-8'))
       """Exception: AttributeError: 'str' object has no attribute 'read'"""

       raw_json = json.loads(req.stream.read(), 'UTF-8')
       """Exception: TypeError: the JSON object must be str, not 'bytes'"""

       raw_json = json.loads(req.stream, 'UTF-8')
       """TypeError: the JSON object must be str, not 'Body'"""

I'm on the way of giving up, but if somebody can tell me why this is happening and how to parse JSON in Falcon i would be extremely thankful.

Thanks

Environment: OSX Sierra Python 3.5.2 Falcon and other is the latest version from Pip

Upvotes: 1

Views: 2214

Answers (2)

Eric PASCUAL
Eric PASCUAL

Reputation: 219

You have to invoke encode() on the bytes returned by read() with something like req.stream.read().encode('utf-8').

This way the bytes are converted to a str as expected by json.loads().

The other way not to bother with all this boring and error prone encode/decode and bytes/str stuff (which BTW differs in Py2 and Py3), is to use simplejson as a replacement for json. It is API compatible, so the only change is to replace import json with import simplejson as json in your code.

In addition, it simplifies the code since reading the body can be done with json.load(req.bounded_stream), which is much shorter and more readable than json.loads(req.bounded_stream.read().encode('utf-8')).

I now do it this way, and don't use the standard json module any more.

Upvotes: 1

anekix
anekix

Reputation: 2563

your code should work if other pieces of code are in place . a quick test(filename app.py):

import falcon
import json

class JSON_Middleware(object):
    def process_request(self, req, resp):
       raw_json = json.loads(req.stream.read())
       print raw_json

class Test:
    def on_post(self,req,resp):
        pass

app = application = falcon.API(middleware=JSON_Middleware())
t = Test()
app.add_route('/test',t)

run with: gunicorn app
$ curl -XPOST 'localhost:8000' -d '{"Hello":"wold"}'

Upvotes: 2

Related Questions