Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I return a JSON array with Bottle?

Tags:

python

bottle

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?

like image 723
Mark Bell Avatar asked Sep 06 '12 06:09

Mark Bell


People also ask

Can JSON return array?

Arrays in JSON are almost the same as arrays in JavaScript. In JSON, array values must be of type string, number, object, array, boolean or null. In JavaScript, array values can be all of the above, plus any other valid JavaScript expression, including functions, dates, and undefined.


2 Answers

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) 
like image 135
Vinay Sajip Avatar answered Sep 21 '22 14:09

Vinay Sajip


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"}]} 
like image 44
jose.angel.jimenez Avatar answered Sep 21 '22 14:09

jose.angel.jimenez