Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Display JSON returned from Flask in a neat way

Tags:

python

json

flask

I'm creating an API using Flask and have the following code:

@app.route('/<major>/')
def major_res(major):
    course_list = list(client.db.course_col.find({"major": (major.encode("utf8", "ignore").upper())}))
    return json.dumps(course_list, sort_keys=True, indent=4, default=json_util.default)

When viewing /csci/ in the browser, the output looks like this:

[{ "course": "CSCI052", "description": "Fundamentals of Computer Science. A solid foundation in functional programming, procedural and data abstraction, recursion and problem-solving. Applications to key areas of computer science, including algorithms and complexity, computer architecture and organization, programming languages, finite automata and computability. This course serves the same role as HM 60 as a prerequisite for upper-division computer science courses at any of the Claremont Colleges. Prerequisite: 51.", "instructor": "Bull, Everett L.,, Jr.", "name": " Fundamentals of Computer Science", "number": 52, "school": "PO" }]

How do I return this dictionary so that each key and value are on their own line?

like image 857
Aloke Desai Avatar asked Jun 04 '13 02:06

Aloke Desai


People also ask

How do I return a dict as a JSON response from a Flask view?

The Solution. There are two methods you can use to return JSON data in your Flask application's view: by returning a Python dictionary, or by using Flask's jsonify() method.

What does Jsonify return?

jsonify() is a helper method provided by Flask to properly return JSON data. jsonify() returns a Response object with the application/json mimetype set, whereas json. dumps() simply returns a string of JSON data. This could lead to unintended results.


2 Answers

Flask provides jsonify() as a convenience:

from flask import jsonify

@app.route("/<major>/")
def major_res(major):
    course_list = list(client.db.course_col.find({"major": major.upper()}))
    return flask.jsonify(**course_list)

This will return the args of jsonify as a JSON representation, and, unlike your code, will send the proper Content-Type header: application/json. Take note of what the docs say about the format:

This function's response will be pretty printed if the JSONIFY_PRETTYPRINT_REGULAR config parameter is set to True or the Flask app is running in debug mode. Compressed (not pretty) formatting currently means no indents and no spaces after separators.

Responses will receive non-pretty-printed JSON when not in debug mode. This shouldn't be a problem since JSON for JavaScript consumption shouldn't need to be formatted (that's just extra data to be sent over the wire), and most tools format received JSON on their own.

If you'd like to still use json.dumps(), you can send the proper mimetype by returning a Response with current_app.response_class().

from flask import json, current_app

@app.route("/<major>/")
def major_res(major):
    course_list = list(client.db.course_col.find({"major": major.upper() }))
    return current_app.response_class(json.dumps(course_list), mimetype="application/json")

For more on the difference:

  • json.dumps vs flask.jsonify
  • flask.json module docs

Prior to Flask 1.0, JSON handling was somewhat different. jsonify would try to detect whether a request was AJAX and return pretty printed if it was not; this was removed because it was unreliable. jsonify only allowed dicts as the top-level object for security reasons; this is no longer applicable in modern browsers.

like image 75
Bailey Parker Avatar answered Oct 18 '22 21:10

Bailey Parker


If for some reason you need to over-ride flask.jsonify (E.g., adding a custom json encoder) you can do so with the following method that implements the security fix @phpmycoder mentioned:

from json import dumps
from flask import make_response

def jsonify(status=200, indent=4, sort_keys=True, **kwargs):
    response = make_response(dumps(dict(**kwargs), indent=indent, sort_keys=sort_keys))
    response.headers['Content-Type'] = 'application/json; charset=utf-8'
    response.headers['mimetype'] = 'application/json'
    response.status_code = status
    return response

@app.route('/<major>/')
def major_res(major):
    course = client.db.course_col.find({"major": (major.encode("utf8", "ignore").upper())})
    return jsonify(**course)

@app.route('/test/')
def test():
    return jsonify(indent=2, sort_keys=False, result="This is just a test")

Response:

{
    "course": "CSCI052", 
    "description": "Fundamentals of Computer Science. A solid foundation in functional programming, procedural and data abstraction, recursion and problem-solving. Applications to key areas of computer science, including algorithms and complexity, computer architecture and organization, programming languages, finite automata and computability. This course serves the same role as HM 60 as a prerequisite for upper-division computer science courses at any of the Claremont Colleges. Prerequisite: 51.", 
    "instructor": "Bull, Everett L.,, Jr.", 
    "name": " Fundamentals of Computer Science", 
    "number": 52, 
    "school": "PO"
}
like image 45
reubano Avatar answered Oct 18 '22 21:10

reubano