Pydanticで入出力をキャメルケースにする方法をまとめます。
目次
サンプルコード
今回はFastAPI上でPydanticを利用するサンプルコードを使用します。動作を見たい場合は以下のライブラリをインストールしてください。
pip install fastapi uvicorn
# FastAPIサーバー実行
python -m uvicorn testmain:app --reload
以下は今回使うサンプルコードです。
TestBodyがリクエストボディ、TestResがレスポンスの型です。
前半は修正前の入出力がスネークケースのバージョン、後半は修正後のキャメルケースを出力するバージョンです。
from fastapi import Body, FastAPI
from pydantic import BaseModel
app = FastAPI()
class TestRes(BaseModel):
result_message: str
status_code: int
name: str
class TestBody(BaseModel):
first_name: str
last_name: str
@app.post("/test", response_model=TestRes)
def test(body: TestBody = Body()):
return TestRes(
result_message="テストメッセージ",
status_code=200,
name=body.first_name + body.last_name,
)
###############################################
import stringcase
from fastapi import Body, FastAPI
from pydantic import BaseModel
app = FastAPI()
class TestRes(BaseModel):
result_message: str
status_code: int
name: str
class Config:
allow_population_by_field_name = True
alias_generator = stringcase.camelcase
class TestBody(BaseModel):
first_name: str
last_name: str
class Config:
alias_generator = stringcase.camelcase
@app.post("/test", response_model=TestRes)
def test(body: TestBody = Body()):
return TestRes(
result_message="テストメッセージ",
status_code=200,
name=body.first_name + body.last_name,
)
入出力をキャメルケースにする
alias_generatorをConfigに設定することで、入出力のフィールド名を変更できます。
alias_generatorは文字列を引数に取り文字列を返す関数を指定できます。
https://pydantic-docs.helpmanual.io/usage/model_config/#alias-generator
まずはキャメルケースに変換するライブラリをインストール。
pip install stringcase
以下のようにBodyにalias_generatorにstringcase.camelcaseを設定すると、POSTリクエストのBody値はフィールド名と同じスネークケースではエラーが起き、キャメルケースのみ受け付けるようになります。
class TestBody(BaseModel):
first_name: str
last_name: str
class Config:
alias_generator = stringcase.camelcase
"""
以下の値を受け入れるようになる
{
"firstName": "hoge",
"lastName": "haaa"
}
これだとエラー
{
"first_name": "hoge",
"last_name": "haaa"
}
"""
同じようにResponseクラスに指定すると出力がキャメルケースになります。
ただ、alias_generatorを設定するとオブジェクト作成時の引数にも適用されてしまうためキャメルケースで指定する必要があります。
class TestRes(BaseModel):
result_message: str
status_code: int
name: str
class Config:
alias_generator = stringcase.camelcase
@app.post("/test", response_model=TestRes)
def test(body: TestBody = Body()):
# フィールド名はスネークケースだがキャメルケースで指定が必要になる
return TestRes(
resultMessage="テストメッセージ",
statusCode=200,
name=body.first_name + body.last_name,
)
"""
レスポンスは以下のようになる
{
"resultMessage": "テストメッセージ",
"statusCode": 200,
"name": "hogehaaa"
}
"""
フィールド名・alias両方を使えるようにする
先ほどの例ではTestResの引数もキャメルケースを指定しないといけないようになりました。
フィールド名はスネークケースなのにキャメルケースで指定が必要で不自然だったり、フィールド名と違うので静的解析で型のエラーが出たりしてしまいます。
allow_population_by_field_nameをTrueにすることでフィールド名のスネークケースも引数で使えるようになります。出力にはalias_generatorが使用されるのでキャメルケースのままです。
また、Bodyにallow_population_by_field_nameを指定すると、フィールド名のスネークケースでもalias_generatorのキャメルケースどちらでも受け入れるようになります。
class TestRes(BaseModel):
result_message: str
status_code: int
name: str
class Config:
allow_population_by_field_name = True
alias_generator = stringcase.camelcase
@app.post("/test", response_model=TestRes)
def test(body: TestBody = Body()):
# フィールド名で指定ができるようになる
return TestRes(
result_message="テストメッセージ",
status_code=200,
name=body.first_name + body.last_name,
)
"""
レスポンスは以下のようになる
{
"resultMessage": "テストメッセージ",
"statusCode": 200,
"name": "hogehaaa"
}
"""
Bodyはキャメルケースのみ受け付けて、レスポンスは出力キャメルケースで引数はフィールド名(スネークケース)を指定できる最終的なコードは以下のようになります。
import stringcase
from fastapi import Body, FastAPI
from pydantic import BaseModel
app = FastAPI()
class TestRes(BaseModel):
result_message: str
status_code: int
name: str
class Config:
allow_population_by_field_name = True
alias_generator = stringcase.camelcase
class TestBody(BaseModel):
first_name: str
last_name: str
class Config:
alias_generator = stringcase.camelcase
@app.post("/test", response_model=TestRes)
def test(body: TestBody = Body()):
return TestRes(
result_message="テストメッセージ",
status_code=200,
name=body.first_name + body.last_name,
)