Как вернуть массив JSON с помощью Bottle?

Я пишу API, используя бутылки, который до сих пор был фантастическим. Тем не менее, я столкнулся с небольшим препятствием при попытке вернуть массив JSON. Вот мой тестовый код приложения:

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)

когда я запускаю это и запрашиваю каждый маршрут, я получаю ответы JSON, которые я ожидал бы от первых двух маршрутов:

/single

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

/containsarray

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

Итак, я ожидал возвращения списка словари для создания следующего ответа JSON:

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

но просить /array маршрут просто приводит к ошибке. Что я делаю неправильно и как я могу вернуть JSON массив таким образом?

2 ответов


плагин JSON бутылки ожидает, что будут возвращены только дикты-не массивы. Существуют уязвимости, связанные с возвратом массивов JSON-см., например,этот пост об угоне JSON.

Если вам действительно нужно это сделать, это можно сделать, например

@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)

согласно документации бутылки 0.12:

как упоминалось выше, словари Python (или их подклассы) являются автоматически преобразуется в строки JSON и возвращается в браузер с заголовком Content-Type, установленным в application / json. Этот упрощает реализацию API на основе json. Данные форматы json также поддерживаются. См. tutorial-output-filter, чтобы узнать больше.

что означает, что вам не нужно import json ни Установка атрибута content_type ответа.

таким образом, код сильно сокращается:

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

и документ JSON, возвращенный веб-сервером, будет выглядеть так:

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