Flask TypeError 'is not JSON serializable' - nested dictionary
Asked Answered
L

6

8

i am using Flask as framework for my server, and while returning a response i get the following error:

> Traceback (most recent call last):
  File "C:\Python27\lib\site-packages\flask\app.py", line 1612, in full_dispatch_request
    rv = self.dispatch_request()
  File "C:\Python27\lib\site-packages\flask\app.py", line 1598, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "C:\Python27\lib\site-packages\flask_restful\__init__.py", line 480, in wrapper
    resp = resource(*args, **kwargs)
  File "C:\Python27\lib\site-packages\flask\views.py", line 84, in view
    return self.dispatch_request(*args, **kwargs)
  File "C:\Python27\lib\site-packages\flask_restful\__init__.py", line 595, in dispatch_request
    resp = meth(*args, **kwargs)
  File "rest.py", line 27, in get
    return jsonify(**solution)
  File "C:\Python27\lib\site-packages\flask\json.py", line 263, in jsonify
    (dumps(data, indent=indent, separators=separators), '\n'),
  File "C:\Python27\lib\site-packages\flask\json.py", line 123, in dumps
    rv = _json.dumps(obj, **kwargs)
  File "C:\Python27\lib\json\__init__.py", line 251, in dumps
    sort_keys=sort_keys, **kw).encode(obj)
  File "C:\Python27\lib\json\encoder.py", line 209, in encode
    chunks = list(chunks)
  File "C:\Python27\lib\json\encoder.py", line 434, in _iterencode
    for chunk in _iterencode_dict(o, _current_indent_level):
  File "C:\Python27\lib\json\encoder.py", line 408, in _iterencode_dict
    for chunk in chunks:
  File "C:\Python27\lib\json\encoder.py", line 332, in _iterencode_list
    for chunk in chunks:
  File "C:\Python27\lib\json\encoder.py", line 332, in _iterencode_list
    for chunk in chunks:
  File "C:\Python27\lib\json\encoder.py", line 442, in _iterencode
    o = _default(o)
  File "C:\Python27\lib\site-packages\flask\json.py", line 80, in default
    return _json.JSONEncoder.default(self, o)
  File "C:\Python27\lib\json\encoder.py", line 184, in default
    raise TypeError(repr(o) + " is not JSON serializable")
TypeError: {'origin': u'porto', 'dest': u'lisboa', 'price': '31', 'date': '2017-12-23', 'url': u'https://www.google.pt/flights/#search;f=opo;t=lis;d=2017-12-23;r=2017-12-24'} is not JSON serializable

i have the following function:

from flask import Flask, request, jsonify
from flask_restful import Resource, Api
from flask_cors import CORS, cross_origin
from json import dumps
import flights
import solveProblem

app = Flask(__name__)
api = Api(app)
CORS(app)

class Flights(Resource):
    def get(self, data):
        print 'received data from client: ' + data
        solution = solveProblem.solve(data)
        print 'got the solution from the script! \nSOLUTION: \n'
        print solution
        return jsonify(solution)

api.add_resource(Flights, '/flights/<string:data>')

if __name__ == '__main__':
    app.run()

while debugging the problem, i found the following solutions which did not work:

1) return solution instead of {'solution': solution}

2) do jsonify(solution)

3) do jsonify(**solution)

none of the above worked for me; i wonder why this happens, when i am trying to return a valid dictionary:

{'flights': [[{'origin': u'porto', 'dest': u'lisboa', 'price': '31', 'date': '2017-12-23', 'url': u'https://www.google.pt/flights/#search;f=opo;t=lis;d=2017-12-23;r=2017-12-24'}]], 'cost': '31'}

any help is appreciated. Thanks

Lancelancelet answered 1/9, 2017 at 18:41 Comment(7)
What's the type of solution? Can you print type(solution) and print repr(solution) and share the output?Expression
solution if of type dict, but i just noticed that soltuin['flights][0][0] (the 'dict'-) inside, is not of type dict but of class 'Thesis.modules.Flight.Flight'> i guess this is the error, any suggestions on how to fix it? @smarxLancelancelet
Yup, that sounds like the issue. Either implement a custom JSONEncoder or convert the data to something JSON-serializable first.Expression
by the way, that type is a result of returning the following : def __repr__(self): #logger.info('INSIDE REPR') # return "origin: {}, destination: {}, date: {}, price: {} url: {}".format( # self._origin, self._dest, self._date, self._price, self._url) f_dict = { "origin": self._origin[0], "dest": self._dest[0], "date": self._date, "price": self._price, "url": self._url } return str(f_dict) i'd like to return a dictionary, but python does not allow it, so i used strLancelancelet
__repr__ has to return a str, of course, but I don't see how that's related to the problem you're having.Expression
Can you try return jsonify(dumps(solution, default=lambda o: o.__dict__)). I feel that should do the jobCuttle
Instead of return str(f_dict) have you tried to return return { "origin": str(self._origin[0]), "dest": str(self._dest[0]), "date": str(self._date), "price": str(self._price), "url": str(self._url) }? This way you should have a valid object, or at least being able to further identify where's the bug in all those fields.Drumhead
L
-2

As I found out, this error generally occurs when the response is not a pure python dictionary. This happened to me because I was trying to pass a class object. So, to solve the problem, i created a class method which returns a dictionary describing the object, and use this to create the json response.

Conclusion: Use Pure python objects, which are easily translated to JSON.

Lancelancelet answered 10/4, 2018 at 23:2 Comment(0)
P
7

My guess is when you were creating 'solution', the data that got assigned to it was an incorrectly formatted dictionary

    {'item', 'value'}

Instead of:

    {'item': 'value'}

Thus creating a set instead of a dict

Poverty answered 30/3, 2020 at 20:39 Comment(0)
T
0

In flask-restful, Resource class get method will just need to return python data structure. So just remove jsonify. For User Defined Object, you can use marshal_with() decorator. See more: https://flask-restful.readthedocs.io/en/latest/quickstart.html#a-minimal-api

Tacheometer answered 23/1, 2018 at 4:21 Comment(1)
Doesn't work. Still complains it's not json seralizable.Headed
M
0

we cannot directly use the jsonify when your trying to converting list of data into json. there is two approaches are there you can convert list into dictionary for that we need to write function that convert your list data into dictionary which is complicated task . there is one smart work you can use Marshmallow library . it serialized you list data after that you can use jsonify.

Matrona answered 15/5, 2020 at 18:18 Comment(0)
D
-1

Since most of your functions are declared elsewhere, I worked a toy Flask program just to pass the dictionary you got stuck with. [Edit] Before I was using the standard python json module. I edited it to use flask's own jsonify, and it works with the direct dictionary still. So the error is not where the OP is looking for.

 {'flights': [[{'origin': u'porto', 'dest': u'lisboa', 'price': '31', 'date': '2017-12-23', 'url': u'https://www.google.pt/flights/#search;f=opo;t=lis;d=2017-12-23;r=2017-12-24'}]], 'cost': '31'}

The following program runs and returns the dictionary as a JSON object:

import flask

app = flask.Flask(__name__)

@app.route('/')
def hello():
    jdic = flask.jsonify( {'origin': u'porto', 'dest': u'lisboa', 'price': '31', 'date': '2017-12-23', 'url': u'https://www.google.pt/flights/#search;f=opo;t=lis;d=2017-12-23;r=2017-12-24'} )
    return jdic

if __name__ == '__main__':
    app.run()
Drumhead answered 1/9, 2017 at 19:4 Comment(0)
L
-2

As I found out, this error generally occurs when the response is not a pure python dictionary. This happened to me because I was trying to pass a class object. So, to solve the problem, i created a class method which returns a dictionary describing the object, and use this to create the json response.

Conclusion: Use Pure python objects, which are easily translated to JSON.

Lancelancelet answered 10/4, 2018 at 23:2 Comment(0)
P
-3

I had the same problem with a 3 level Nested Dictionary; it was valid, json serializable and via command line json.dumps had no issue. However, Flask did not want to output it: "TypeError", not json serializable. The only difference is that I am using Python 3.5.

So I made a copy of it as a string (that on command line was json serializable!) and passed to Flask output, it worked.

Try to pass the nested json as

eval(str(solution))

and see the error. It's not a definitive solution but more a workaround.

Hope it helps.

Preferable answered 5/12, 2017 at 11:33 Comment(2)
This looks particularly dangerous if you handle user-provided data.Stereotaxis
True. User input should be always sanitized before any operation on it. But this is not the question' focusPreferable

© 2022 - 2024 — McMap. All rights reserved.