-
-
Notifications
You must be signed in to change notification settings - Fork 18.7k
Closed
Labels
Description
Hello,
I'm trying to build a RESTful api with Flask-RESTful which will return Pandas DataFrame as JSON data.
from flask import Flask
from flask.ext import restful
from flask.ext.restful import Resource, Api
import pandas as pd
import click
import logging
app = Flask(__name__)
api = restful.Api(app)
class DataWebservice(Resource):
def get(self, size):
logging.info("get %d" % size)
# get DB conn
# df = pd.read_sql(...) # USE LIMIT
df = pd.DataFrame({"col1": [1]*size, "col2": [2]*size})
#return(df.to_json())
return(df)
api.add_resource(DataWebservice, '/api/v1/solar/df/get/<int:size>')
@click.command()
@click.option('--host', default='127.0.0.1', \
help="host (127.0.0.1 or 0.0.0.0 to accept all ip)")
@click.option('--debug/--no-debug', default=False, help="debug mode")
def main(debug, host):
app.run(host=host, debug=debug)
if __name__ == '__main__':
main()
I run server using
$ python server.py --debug
I run client using
$ curl http://127.0.0.1:5000/api/v1/solar/df/get/10
but I get the following error
TypeError: col1 col2
0 1 2
1 1 2
...
8 1 2
9 1 2
[10 rows x 2 columns] is not JSON serializable
So it seems that Pandas DataFrame are not JSON serializable.
I try this using IPython
size = 10
df = pd.DataFrame({"col1": [1]*size, "col2": [2]*size})
json.dumps(df)
It raises same error.
I'm aware that DataFrame have method named to_json()
but it doesn't help me much as my server will return escaped strings such as
"{\"col1\":{\"0\":1,\"1\":1,\"2\":1,\"3\":1,\"4\":1,\"5\":1,\"6\":1,\"7\":1,\"8\":1,\"9\":1},\"col2\":{\"0\":2,\"1\":2,\"2\":2,\"3\":2,\"4\":2,\"5\":2,\"6\":2,\"7\":2,\"8\":2,\"9\":2}}"
see flask-restful/flask-restful#269
Kind regards
Metadata
Metadata
Assignees
Labels
Type
Projects
Milestone
Relationships
Development
Select code repository
Activity
jreback commentedon Jul 8, 2014
what are you asking here? pandas provides a read/write API to JSON: http://pandas.pydata.org/pandas-docs/stable/io.html#json, which should be deserializable by foreign JSON parsers. You must use
.to_json()
as a dataframe as many custom types.s-celles commentedon Jul 8, 2014
Hello,
Thanks I know
to_json()
methodI thought Pandas DataFrame could inherit an other class to become directly "JSON serializable".
So
json.dumps(df)
could return exactly the same result asdf.to_json()
.So in this Flask view we could directly return DataFrame (in fact
jsonify(df)
) instead of doing:But maybe I'm wrong and there is no way for
json.dumps(df)
to return a JSON string.I thought that what I'm asking is more a syntactic sugar than a major improvement.
Kind regards
jreback commentedon Jul 8, 2014
This is the typical way to extend the default json encoder
s-celles commentedon Jul 8, 2014
So you think it's better to define our own JSONEncoder. The problem is that I don't think jsonify support cls argument for encoder... but that's an other problem
Moreover I noticed
it's like a string inside a string...
What I want to encode is in fact
I know I can do
but I feel that's not the right way of doing
jreback commentedon Jul 8, 2014
HTH
their are lots of options for
to_json()
, see docs: http://pandas.pydata.org/pandas-docs/stable/io.html#jsonnot really sure what you are doing
closing this as its out of scope for pandas.
s-celles commentedon Jul 8, 2014
Please try this:
it returns
unicode
I could expectdict
jreback commentedon Jul 8, 2014
you need to teach
json
how to do this by defining an object hook. http://www.yilmazhuseyin.com/blog/dev/advanced_json_manipulation_with_python/s-celles commentedon Jul 8, 2014
Thanks for this tutorial but there is a difference between the 2 serialized versions
Is there a clean solution with a custom encoder for object with to_json method (like DataFrame) to output correctly JSON (without extra quotes)
jreback commentedon Jul 8, 2014
this is maybe a question for SO, I don't use custom uncoders at all. It seems a whole lot simpler for you to simply call
df.to_json()
which returns a string no? (then since you know the structure, then justpd.read_json()
when you need to.s-celles commentedon Jul 8, 2014
I understand your reply... but imagine you have several dataframes to output into the same JSON message.... doing things this way is not very clear. I think it's much more clear to have a dict structure which can contains several df (and other data) and after serialize it.
About deserialization... yes that's not a problem... I know structure and where are dataframes.
jreback commentedon Jul 8, 2014
ok, as I said, you maybe want to do custom encoding/decoding like I showed above. You need to write that. a dataframe can be turned into json via
to_json
and read byread_json
. when to do that is up 2 u.s-celles commentedon Jul 8, 2014
It works much better with this custom encoder (with
to_dict
method):There is no extra quotes.
Thanks
s-celles commentedon Jul 8, 2014
Problem is that in fact I can't use 'orient' parameter which is very convenient to reduce message size. Maybe a
to_object(orient='...')
could be a good idea and could be call byto_json
wegry commentedon Oct 24, 2016
@scls19fr this is obviously an old issue, but seeing as I stumbled upon it. The easiest way to nest a dataframe in a larger JSON blob is to use
s-celles commentedon Oct 25, 2016
Thanks @wegry I'm aware of #8486 which closes #7840
Abir0802 commentedon Oct 13, 2017
you can use make_response from flask , e.g.
resp = make_response(df.to_json(orient = "records"))
and then simply return it.
shwetasit commentedon Oct 11, 2018
This saved my life. Thank you!
arpitr07 commentedon Mar 31, 2020
Thanks, Abir0802. Was stuck here for a while.
xuancong84 commentedon Apr 21, 2020
Well, there are too many Python-specific data types which JSON cannot serialize/deserialize. Take a look at the following nested data structure and you will immediately realize how many things JSON cannot handle:
I have recently developed a comprehensive utility pandas-serializer, which can serialize/deserialize almost everything (exactly everything as shown above). My utility does not depend on JSON at all and it uses native Python eval/repr/str to serialize and deserialize. You are welcome to try and see what cannot be identically deserialized, and report to me. Thanks! -:)
kopeclu2 commentedon Nov 17, 2021
That is the solution 👍 💯