Search code examples
pythontemplatesflaskrenderquart

Quart/Flask render_template return compact json


I'm using Quart (which essentially Flask for HTTP/2) to serve some JSON content. The JSON content resides in the templates/ directory in a pretty-print format, e.g.

example.json

{
  "key1": "value1",
  "list1": [
    {
      "key2": "{{ keyword_arg2 or "value2"}}",
      "list2": [
        {
          "key3": "value3 with spaces",
          "key4": "value4"
        }
      ]
    }
  ]
}

If I just return render_template('example.json'), it will preserve all the whitespace in the original file. I would like to return a compact form of that, i.e.

{"key1":"value1","list1":[{"key2":"value2","list2":[{"key3":"value3 with spaces","key4":"value4"}]}]}

Is there a good way to do that (and ideally to also set the content-type as application/json). What I've come up with so far is this:

body = await render_template('example.json')
body = body.replace('\n', '')
body = ''.join(body.split())
r = await make_response(body)
r.headers.set('Content-type', 'application/json')
return r

But it doesn't handle spaces in the values very well (this version removes them entirely). The jsonify function in Quart does the automatic setting of Content-type to application/json, but it doesn't seem to operate well on the string returned by render_template, unless I'm using it wrongly.


Solution

  • The render_template will return a string which you can then parse as JSON and return from the route. This will then return a JSON response using the app's JSON configuration values, the defaults are linked here e.g.

    import json
    
    @app.get("/")
    async def route():
        body = await render_template('example.json')
        data = json.loads(body)
        return data
    

    Note that returning a dictionary from a Quart route is equivalent to calling jsonify and returning that result.