Mysterio
Mysterio

Reputation: 3427

How to access a json POST data in Flask RESTful API app

I'm currently stuck trying to get access to a POST json data in a flask RESTful API app. The POST data is simply a Pandas dataframe converted into a json object with the pandas.to_json() method.

import pandas as pd
from flask import Flask, request, jsonify
from flask_restful import Resource, Api


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

# Creation Of Main Endpoint Classes
class Test(Resource):
    def post(self):

        # Get POST data as json & read it as a DataFrame
        new_x = request.get_json()

        current_data = pd.read_json(new_x)
        return {'message': 'POST data read successfully'}

# Addition of the Endpoint Classes As Endpoints For The RESTFul API
api.add_resource(Test, '/api/v1')


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

After making a POST request to this Test endpoint, I get a JSONDecodeError: Expecting value error. The post is made with requests python library as:

import requests
new_json = df.to_json()
post_url = 'http://127.0.0.1:5000/api/v1'
post_r = requests.post(url=post_url, data=new_json_orient)
print(post_r.json())

The stack trace seems to point out that request.get_json() returns a None with <class 'NoneType'>. Pandas, as a result, can't read the None. Pandas and I are missing the location of the POST data.

127.0.0.1 - - [08/Mar/2019 13:06:56] "POST /api/v1 HTTP/1.1" 500 -
Traceback (most recent call last):
  File "C:\Users\..\AppData\Local\Continuum\anaconda3\envs\..\lib\site-packages\flask\app.py", line 2309, in __call__
    return self.wsgi_app(environ, start_response)
  File "C:\Users\..\AppData\Local\Continuum\anaconda3\envs\..\lib\site-packages\flask\app.py", line 2295, in wsgi_app
    response = self.handle_exception(e)
  File "C:\Users\..\AppData\Local\Continuum\anaconda3\envs\..\lib\site-packages\flask_restful\__init__.py", line 273, in error_router
    return original_handler(e)
  File "C:\Users\..\AppData\Local\Continuum\anaconda3\envs\..\lib\site-packages\flask\app.py", line 1741, in handle_exception
    reraise(exc_type, exc_value, tb)
  File "C:\Users\..\AppData\Local\Continuum\anaconda3\envs\..\lib\site-packages\flask\_compat.py", line 34, in reraise
    raise value.with_traceback(tb)
  File "C:\Users\..\AppData\Local\Continuum\anaconda3\envs\..\lib\site-packages\flask\app.py", line 2292, in wsgi_app
    response = self.full_dispatch_request()
  File "C:\Users\..\AppData\Local\Continuum\anaconda3\envs\..\lib\site-packages\flask\app.py", line 1815, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "C:\Users\..\AppData\Local\Continuum\anaconda3\envs\..\lib\site-packages\flask_restful\__init__.py", line 273, in error_router
    return original_handler(e)
  File "C:\Users\..\AppData\Local\Continuum\anaconda3\envs\..\lib\site-packages\flask\app.py", line 1718, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File "C:\Users\..\AppData\Local\Continuum\anaconda3\envs\..\lib\site-packages\flask\_compat.py", line 34, in reraise
    raise value.with_traceback(tb)
  File "C:\Users\..\AppData\Local\Continuum\anaconda3\envs\..\lib\site-packages\flask\app.py", line 1813, in full_dispatch_request
    rv = self.dispatch_request()
  File "C:\Users\..\AppData\Local\Continuum\anaconda3\envs\..\lib\site-packages\flask\app.py", line 1799, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "C:\Users\..\AppData\Local\Continuum\anaconda3\envs\..\lib\site-packages\flask_restful\__init__.py", line 480, in wrapper
    resp = resource(*args, **kwargs)
  File "C:\Users\..\AppData\Local\Continuum\anaconda3\envs\..\lib\site-packages\flask\views.py", line 88, in view
    return self.dispatch_request(*args, **kwargs)
  File "C:\Users\..\AppData\Local\Continuum\anaconda3\envs\..\lib\site-packages\flask_restful\__init__.py", line 595, in dispatch_request
    resp = meth(*args, **kwargs)
  File "C:\Users\..\Documents\..\app.py", line 35, in post
    current_data = pd.read_json(new_x)
  File "C:\Users\..\AppData\Local\Continuum\anaconda3\envs\..\lib\site-packages\pandas\io\json\json.py", line 413, in read_json
    path_or_buf, encoding=encoding, compression=compression,
  File "C:\Users\..\AppData\Local\Continuum\anaconda3\envs\..\lib\site-packages\pandas\io\common.py", line 232, in get_filepath_or_buffer
    raise ValueError(msg.format(_type=type(filepath_or_buffer)))
ValueError: Invalid file path or buffer object type: <class 'NoneType'>

What am I doing wrong? How can I access the new_json POST data? Thanks in advance.

Upvotes: 1

Views: 10729

Answers (1)

vahdet
vahdet

Reputation: 6729

It is most probably because the POST method does not contain any info for the Content-Type of it.

  1. If the requests version is newer than 2.4.2, you can use json instead of data for post body (see doc details here). This will automatically set the header 'Content-Type': 'application/json':
post_r = requests.post(url=post_url, json=new_json_orient)
  1. If requests of your use is older, you can explicitly set the header value as:
headers = {'Content-type': 'application/json'}
post_r = requests.post(url=post_url, data=new_json_orient, headers=headers)

P.S. For more about Content-Type header mentioned so much in this post, here's the link for MDN docs.

Upvotes: 3

Related Questions