レスポンスを直接返す¶
🌐 AI と人間による翻訳
この翻訳は、人間のガイドに基づいて AI によって作成されました。🤝
原文の意図を取り違えていたり、不自然な表現になっている可能性があります。🤖
AI LLM をより適切に誘導するのを手伝う ことで、この翻訳を改善できます。
FastAPI の path operation では、通常は任意のデータを返すことができます: 例えば、dict、list、Pydanticモデル、データベースモデルなどです。
レスポンスモデル を宣言した場合、FastAPI は Pydantic を使ってデータをJSONにシリアライズします。
レスポンスモデルを宣言しない場合、FastAPI は JSON互換エンコーダ で説明されている jsonable_encoder を使用し、その結果を JSONResponse に入れます。
また、JSONResponse を直接作成して返すこともできます。
Tip
通常は、JSONResponse を直接返すよりも、レスポンスモデル を使うほうがパフォーマンスが大幅に良くなります。これは、Pydantic によるシリアライズが Rust で実行されるためです。
Response を返す¶
実際は、Response やそのサブクラスを返すことができます。
Info
JSONResponse それ自体は、Response のサブクラスです。
Response を返した場合は、FastAPI は直接それを返します。
それは、Pydanticモデルのデータ変換や、コンテンツを任意の型に変換したりなどはしません。
これは多くの柔軟性を提供します。任意のデータ型を返したり、任意のデータ宣言やバリデーションをオーバーライドできます。
同時に多くの責任も伴います。返すデータが正しく、正しいフォーマットであり、シリアライズ可能であることなどを、あなたが保証しなければなりません。
jsonable_encoder を Response の中で使う¶
FastAPI はあなたが返す Response に対して何も変更を加えないので、コンテンツが準備できていることを保証しなければなりません。
例えば、Pydanticモデルを JSONResponse に含めるには、すべてのデータ型 (datetime や UUID など) をJSON互換の型に変換された dict に変換しなければなりません。
このようなケースでは、レスポンスにデータを含める前に jsonable_encoder を使ってデータを変換できます。
from datetime import datetime
from fastapi import FastAPI
from fastapi.encoders import jsonable_encoder
from fastapi.responses import JSONResponse
from pydantic import BaseModel
class Item(BaseModel):
title: str
timestamp: datetime
description: str | None = None
app = FastAPI()
@app.put("/items/{id}")
def update_item(id: str, item: Item):
json_compatible_item_data = jsonable_encoder(item)
return JSONResponse(content=json_compatible_item_data)
技術詳細
また、from starlette.responses import JSONResponse も利用できます。
FastAPI は開発者の利便性のために fastapi.responses という starlette.responses と同じものを提供しています。しかし、利用可能なレスポンスのほとんどはStarletteから直接提供されます。
カスタム Response を返す¶
上記の例では必要な部分を全て示していますが、あまり便利ではありません。item を直接返すことができるし、FastAPI はそれを dict に変換して JSONResponse に含めてくれるなど。すべて、デフォルトの動作です。
では、これを使ってカスタムレスポンスをどう返すか見てみましょう。
XMLレスポンスを返したいとしましょう。
XMLを文字列にし、Response に含め、それを返します。
from fastapi import FastAPI, Response
app = FastAPI()
@app.get("/legacy/")
def get_legacy_data():
data = """<?xml version="1.0"?>
<shampoo>
<Header>
Apply shampoo here.
</Header>
<Body>
You'll have to use soap here.
</Body>
</shampoo>
"""
return Response(content=data, media_type="application/xml")
Response Model の仕組み¶
path operation で Response Model - 戻り値の型 を宣言すると、FastAPI はそれを使って Pydantic によりデータをJSONにシリアライズします。
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
description: str | None = None
price: float
tax: float | None = None
tags: list[str] = []
@app.post("/items/")
async def create_item(item: Item) -> Item:
return item
@app.get("/items/")
async def read_items() -> list[Item]:
return [
Item(name="Portal Gun", price=42.0),
Item(name="Plumbus", price=32.0),
]
これは Rust 側で行われるため、通常の Python と JSONResponse クラスで行う場合より、パフォーマンスははるかに良くなります。
response_model や戻り値の型を使用する場合、FastAPI はデータ変換に(低速になりうる)jsonable_encoder も JSONResponse クラスも使いません。
代わりに、response model(または戻り値の型)を使って Pydantic が生成した JSON のバイト列をそのまま用い、JSON 用の正しいメディアタイプ(application/json)を持つ Response を直接返します。
備考¶
Response を直接返す場合、バリデーションや、変換 (シリアライズ) や、自動ドキュメントは行われません。
しかし、Additional Responses in OpenAPIに記載されたようにドキュメントを書くこともできます。
後のセクションで、カスタム Response を使用・宣言しながら、自動的なデータ変換やドキュメンテーションを行う方法を説明します。