How do I return a JSON array with Bottle?

35,062

Solution 1

Bottle's JSON plugin expects only dicts to be returned - not arrays. There are vulnerabilities associated with returning JSON arrays - see for example this post about JSON hijacking.

If you really need to do this, it can be done, e.g.

@route('/array')
def returnarray():
    from bottle import response
    from json import dumps
    rv = [{ "id": 1, "name": "Test Item 1" }, { "id": 2, "name": "Test Item 2" }]
    response.content_type = 'application/json'
    return dumps(rv)

Solution 2

According to Bottle's 0.12 documentation:

As mentioned above, Python dictionaries (or subclasses thereof) are automatically transformed into JSON strings and returned to the browser with the Content-Type header set to application/json. This makes it easy to implement json-based APIs. Data formats other than json are supported too. See the tutorial-output-filter to learn more.

Which means you don't need to import json nor setting the content_type attribute of the response.

Thus, the code gets hugely reduced:

@route('/array')
def returnarray():
    rv = [{ "id": 1, "name": "Test Item 1" }, { "id": 2, "name": "Test Item 2" }]
    return dict(data=rv)

And the JSON document returned by the Web server would look like:

{"data": [{"id": 1, "name": "Test Item 1"}, {"id": 2, "name": "Test Item 2"}]}
Share:
35,062
Mark Bell
Author by

Mark Bell

I'm a web developer based in Devon, UK.

Updated on March 16, 2020

Comments

  • Mark Bell
    Mark Bell over 4 years

    I'm writing an API using Bottle, which so far has been fantastic. However, I've run up against a small hurdle when trying to return a JSON array. Here's my test app code:

    from bottle import route, run
    
    @route('/single')
    def returnsingle():
        return { "id": 1, "name": "Test Item 1" }
    
    @route('/containsarray')
    def returncontainsarray():
        return { "items": [{ "id": 1, "name": "Test Item 1" }, { "id": 2, "name": "Test Item 2" }] }
    
    @route('/array')
    def returnarray():
        return [{ "id": 1, "name": "Test Item 1" }, { "id": 2, "name": "Test Item 2" }]
    
    run(host='localhost', port=8080, debug=True, reloader=True)
    

    When I run this and request each route, I get the JSON responses I'd expect from the first two routes:

    /single

    { id: 1, name: "Test Item 1" }
    

    /containsarray

    { "items": [ { "id": 1, "name": "Test Item 1" }, { "id": 2, "name": "Test Item 2" } ] }
    

    So, I had expected returning a list of dictionaries to create the following JSON response:

    [ { "id": 1, "name": "Test Object 1" }, { "id": 2, "name": "Test Object 2" } ]
    

    But requesting the /array route just results in an error. What am I doing wrong, and how can I return a JSON array in this manner?

  • Mark Bell
    Mark Bell almost 12 years
    Thanks, that's an interesting article. Good to know I can still do this if I'm careful, though!
  • crunkchitis
    crunkchitis over 11 years
    Thanks a million for this one.
  • Dacav
    Dacav over 10 years
    Javascript, why on the earth would you do that? Thanks man, here your +1
  • Tejas Tank
    Tejas Tank about 7 years
    Most correct way of code bottle json response. thanks.