Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flask request.get_json() returns string not json

Tags:

python

json

flask

using Flask 1.0.2 on Windows and Python 3.6 64bit first i send data via jquery ajax call, which on JS side is valid json

var myData = '{ "id": "' +clickedID +'" }'
$.ajax({
    type: "POST", // HTTP method POST or GET
    contentType: 'application/json; charset=utf-8', //content type
    url: $SCRIPT_ROOT + '/colors/delete', //Where to make Ajax calls
    dataType:'json', // Data type, HTML, json etc.
    processData: false,
    data:JSON.stringify(myData), 
});

in flask I catch the POST request and try to parse it:

if request.method == "POST":
    print("got request method POST")
if request.is_json:
    print("is json")
    data_json = request.get_json(force=True)
    data_req = request.data
    print("{} is {}".format(data_req, type(data_req)))
    print("{} is {}".format(data_json, type(data_json)))
    data_json2 = json.loads(request.get_json(silent=True, force=True))
    print("{} is {}".format(data_json2, type(data_json2)))
    print (request.json.keys())

with the result:

got request: POST
is json
b'"{ \\"id\\": \\"1\\" }"' is <class 'bytes'>
{ "id": "1" } is <class 'str'>
{'id': '1'} is <class 'dict'>
print (request.json.keys())
AttributeError: 'str' object has no attribute 'keys'
like image 930
Baki Avatar asked Dec 01 '18 10:12

Baki


2 Answers

JSON.stringify() takes a Javascript object and turns it into a JSON string. You're not passing it an object, you're passing it a string, which is then converted into JSON again.

Because the request data contains double-encoded JSON, the request.json attribute gives you back a string rather than a dictionary.

To fix, change:

var myData = '{ "id": "' +clickedID +'" }'

to:

var myData = { id: clickedID }
like image 123
Will Keeling Avatar answered Sep 28 '22 06:09

Will Keeling


In overview, you serialise an object to JSON, which is in effect a string, POST it using the JSON data type, then deserialise it to get the object back. Some objects are easy to serialise and de-serialise with off the shelf functions). See an example based your code modified below (Ignore the CORS as that's due to my test evironment set up).

import logging, json
from flask import Flask, request, jsonify
from flask_cors import CORS
app = Flask(__name__)
CORS(app)

@app.route("/api",methods=['POST'])
def hello():
    logging.info('hello')
    if request.method == "POST":
        print("got request method POST")
    if request.is_json:
        print("is json")
        data = request.get_json()
        print("type of data {}".format(type(data))) # type dict
        print("data as string {}".format(json.dumps(data)))
        print ("keys {}".format(json.dumps(data.keys())))
    return jsonify(message='success')

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

<html>
    <style>
    </style>
    <button onClick="_ajax()">POST</button>
    <script src="jquery.js"></script>
    <script>
        const url_path = "http://localhost:5000/api";
        function _ajax() {
            console.log('_ajax called');
            var xhttp = new XMLHttpRequest();
            var clickedID="testClickedID";
            var myData = {"id": clickedID};
            $.ajax({
                type: "POST", // HTTP method POST or GET
                contentType: 'application/json; charset=utf-8', //content type
                url: url_path, //Where to make Ajax calls
                dataType:'json', // Data type, HTML, json etc.
                processData: false,
                data: JSON.stringify(myData), 
            }).done(
                function(data) {
                    console.log(data);
                }
            );
        }
    </script>
</html>
like image 32
Steve Avatar answered Sep 28 '22 06:09

Steve