概要
今回は pydantic_xml を使って fastapi で XML レスポンスを返却する方法を考えます
環境
- Python 3.11.3
- fastapi 0.100.1
- pydantic-xml 1.0.0
サンプルコード
- vim ./app.py
from fastapi import FastAPI, Response
from pydantic_xml import BaseXmlModel, element
app = FastAPI()
class User(BaseXmlModel, tag="User"):
name: str = element(tag="Name")
age: int = element(tag="Age")
@app.get("/", response_class=Response)
def xml():
data = """<?xml version="1.0"?>
<User>
<Name>hawksnowlog</Name>
<Age>10</Age>
</User>
"""
result = User.from_xml(data)
return Response(content=result.to_xml(), media_type="application/xml")
動作確認
-
pipenv run uvicorn app:app --reload
- curl -v localhost:8000/
=> <User><Name>hawksnowlog</Name><Age>10</Age></User>
解説
XML の構造を pydantic で扱うには pydantic_xml.BaseXmlModel を使います
各エレメントごとにクラスの属性として定義することができます
今回は単純な文字列と数字のフィールドなので element を使っています
タグ内の属性などを扱うこともできるので必要に応じて BaseXmlModel の定義を変更してください
実際にオブジェクトを作成する際は今回は文字列の XML 情報から from_xml メソッドを使って User オブジェクトを作成しています
更にそこから to_xml というシリアライズ用のメソッドが BaseXmlModel に生えているのでそれを使ってレスポンス情報を生成しています
あとは fastapi の Response クラスを使ってデータを application/xml として返却しています
最後に
pydantic-xml を使って fastapi で XML レスポンスを返却する方法を考えてみました
結局この方法だとレスポンスモデルは pydantic で管理できているが最終的なレスポンスは fastapi の Response クラスを使ってしまっているので微妙な気はします (openapi に載らないなど)
本当は response_class に XMLResponse などのクラスを定義して自動でシリアライズしてくれるような便利クラスを作成するほうがいいかなと思います (また検証次第紹介するかも)
0 件のコメント:
コメントを投稿