Подтвердить что ты не робот

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

Я пишу API, используя Bottle, который до сих пор был фантастическим. Тем не менее, я столкнулся с небольшим препятствием при попытке вернуть массив 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, которые я ожидаю от первых двух маршрутов:

/один

{ 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 таким образом?

4b9b3361

Ответ 1

Плагин JSON для бутылок ожидает, что будут возвращены только dicts, а не массивы. Есть уязвимости, связанные с возвратом массивов 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)

Ответ 2

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

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

Это означает, что вам не нужно 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"}]}