web-dev-qa-db-ja.com

Bottleで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)

これを実行して各ルートをリクエストすると、最初の2つのルートから予想される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 routeはエラーになります。私は何を間違えていますか?この方法でJSON配列を返すにはどうすればよいですか?

28
Mark Bell

BottleのJSONプラグインは、配列ではなくdictのみが返されることを期待しています。 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)
74
Vinay Sajip

Bottleの0.12ドキュメントによると:

上記のように、Python辞書(またはそのサブクラス)は自動的にJSON文字列に変換され、Content-Typeヘッダーをapplication/jsonに設定してブラウザーに返されます。これにより、jsonの実装が容易になります。ベースのAPI。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)

また、Webサーバーから返されるJSONドキュメントは次のようになります。

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