Pydantic V2: Essentials: フィールドエイリアス (セクション4-1/13)
Python と JSON 間のフィールド名の違い(snake_case vs. camelCase など)をエイリアス設定で統一・管理できる。
`Field(alias=...)` や `serialization_alias=...`、さらには `alias_generator` を使うことで柔軟なデシリアライズ・シリアライズを実現できる。
`populate_by_name=True` を設定するとフィールド名とエイリアス両方からの入力に対応でき、予約語(`id` など)は `id_` のように工夫して衝突を避けられる。
Python で API を構築し、JSON を扱う際、同じフィールドに異なる名前が必要になることはよくあります。たとえば、JSON データは camelCase で来るのに対し、Python コードでは snake_case が想定されている場合や、`id` のような予約語をモデルのフィールドとして使いたくない場合です。Pydantic V2 は、こういった命名の不一致を処理するための強力な エイリアス の仕組みを提供します。また、外部から受け取るデータ(デシリアライズ)と、自分の API が出力するデータ(シリアライズ)で名前を分けることも可能です。
以下では、エイリアスの定義方法やデフォルト値との組み合わせ、エイリアスの自動生成、さらにフィールド名かエイリアスかを使う設定など、Pydantic でのエイリアス利用を詳細に見ていきます。
なぜエイリアスが必要なのか
異なる規約(Python と JSON)
Python では変数や属性名に `snake_case`(例: `first_name`, `last_name`)を使うのが一般的です。しかし、多くの JSON ベース API では `camelCase`(例: `firstName`, `lastName`)が好まれます。いずれかに合わせるとどちらかが不自然になりがちですが、Pydantic のエイリアス機能を使えば、Python 側は snake_case のまま保ちつつ、JSON は camelCase にすることができます。予約語
Python には `id` や `list`, `filter` など組み込みで使われる単語があります。クラス属性名としてこれらを使うと、少なくともリンタが警告を出したり、紛らわしくなったりします。そこでモデル側では `id_` のようにアンダースコアを付けた名前を使い、JSON の入出力では `id` のままにするといった回避策が必要です。外部と内部での一貫性
外部から受け取るデータが不規則で、奇妙な大文字小文字ルールを持っていたり(例: `"ID"` や `"lastname"`)、社内標準と異なることがよくあります。モデル内部では整理された名前(`id_`, `last_name` など)を使いたい一方で、出力時にはさらに別の整った形式(`"id"`, `"lastName"`)で返したい場合があります。
`Field` を使ったフィールドエイリアスの定義
Pydantic の `Field` オブジェクトは、モデルのフィールドに追加設定を行うための直接的な手段です。たとえば、次のように書く代わりに:
class Person(BaseModel):
id_: int
last_name: str
エイリアスを指定するときは以下のようにします:
from pydantic import BaseModel, Field
class Person(BaseModel):
id_: int = Field(alias="id")
last_name: str = Field(alias="lastName")
デシリアライズ: エイリアス (`"id"`, `"lastName"`) を外部データで探し、Python 側では `id_`, `last_name` として扱います。
シリアライズ: デフォルトでは、Pydantic は Python のフィールド名(`id_`, `last_name`)をそのまま使用します(後述の方法でエイリアスにすることも可能)。
属性へのアクセス
Python 内部では、依然としてクラスの属性は `id_`, `last_name` であり、エイリアス名(`"id"`, `"lastName"`)は有効な属性名とはなりません:
p = Person(id=100, lastName="Gauss")
print(p.id_, p.last_name) # 100 Gauss
hasattr(p, "lastName") # False
`Field` とデフォルト値
デフォルト値も設定したい場合は、`Field(...)` のなかに指定します:
class Example(BaseModel):
id_: int = Field(alias="id", default=100)
description: str = Field(alias="desc", default="N/A")
ここでは、`desc` を省略してもデフォルトの `"N/A"` が適用されます。
シリアライズを制御する: `model_dump(by_alias=True)`
通常、`model_dump()` は Python 上のフィールド名を使って辞書を返します:
m = Person(id=1, lastName="Newton")
print(m.model_dump())
# {'id_': 1, 'last_name': 'Newton'}
もしエイリアスを使った辞書がほしければ、次のようにします:
m.model_dump(by_alias=True)
# {'id': 1, 'lastName': 'Newton'}
JSON にシリアライズするとき(`model_dump_json(by_alias=True)`)でも同様にエイリアスが反映されます。
`populate_by_name` でフィールド名とエイリアスの両方を受け入れる
通常、あるフィールドにエイリアスを定義した場合、入力 データはそのエイリアスを使わないと認識されません。フィールド名(`id_` など)でデータを渡してもエラーになります。これを変更するのが以下のオプションです:
class Model(BaseModel):
model_config = ConfigDict(populate_by_name=True)
id_: int = Field(alias="id")
first_name: str = Field(alias="firstName")
こうしておくと、外部データがエイリアス (`{"id": 10}`) でもフィールド名 (`{"id_": 10}`) でも、どちらでも受理されるようになります。データソースが複数あって名前が混ざるときには便利です。
デシリアライズ用とシリアライズ用で別々のエイリアス
ときには、受信するとき と 送信するとき でまったく違う名前を使いたいことがあります。たとえば、外部 API が `"ID"`, `"FirstName"` というキーで返してくるが、自分の API は `"id"`, `"firstName"` で返したい場合などです。
class Person(BaseModel):
id_: int = Field(alias="ID", serialization_alias="id")
first_name: str = Field(alias="FirstName", serialization_alias="firstName")
last_name: str = Field(alias="lastname", serialization_alias="lastName")
デシリアライズエイリアス (`alias="ID"`, `"FirstName"`, `"lastname"`) は入力に使われる。
シリアライズエイリアス (`serialization_alias="id"`, など) は `by_alias=True` でシリアライズするときに使われる。
これで、外部からは `"ID"` → `id_` → 内部に保持 → シリアライズ時には `"id"` と返す、といった動作が可能になります。
`alias_generator` を使ったエイリアスの自動生成
多数のフィールドで個別にエイリアスを定義するのは大変です。Pydantic では `alias_generator` を設定すれば、Python 側のフィールド名に対して自動的にエイリアスを生成できます。
たとえば、すべてを大文字にしたキーを入力として受け取りたい場合:
def make_upper(s: str) -> str:
return s.upper()
class Person(BaseModel):
model_config = ConfigDict(alias_generator=make_upper)
id_: int
first_name: str | None = None
last_name: str
こうすると、`id_` なら `"ID_"`、`first_name` なら `"FIRST_NAME"`、`last_name` なら `"LAST_NAME"` というエイリアスが自動生成されます。デシリアライズする側はこれらの大文字キーを使わなければなりません。もし特定フィールドだけは別のエイリアスにしたい場合、`Field(alias="...")` を明示的に書けばそちらが優先されます。
Camel Case の場合
Pydantic には `to_camel`, `to_snake`, `to_pascal` という変換関数が用意されています。よくある snake_case → camelCase の変換には `to_camel` を使います:
from pydantic.alias_generators import to_camel
class Person(BaseModel):
model_config = ConfigDict(alias_generator=to_camel)
id_: int
first_name: str
last_name: str
`"first_name"` は `"firstName"` に変換される一方、`id_` はそのままだと `"id_"` になってしまうので、必要に応じて:
id_: int = Field(alias="id")
のように手動でオーバーライドします。
まとめ
ここまで、エイリアスとそれにまつわる便利な設定をいくつも紹介しました。最後に多くの機能を組み合わせた例を示します:
from pydantic import BaseModel, ConfigDict, Field
from pydantic.alias_generators import to_camel
class Person(BaseModel):
model_config = ConfigDict(
alias_generator=to_camel,
populate_by_name=True, # エイリアスとフィールド名どちらでも入力OK
extra="forbid" # 未知のフィールドはエラーにする
)
id_: int = Field(alias="id", default=1) # manual override
first_name: str | None = None
last_name: str
age: int | None = None
# Python 風のフィールド名と camelCase エイリアスを混在
p = Person(id_=10, first_name="Isaac", lastName="Newton", age=84)
print(p)
# Person(id_=10, first_name='Isaac', last_name='Newton', age=84)
# JSON でも同様
data_json = """
{
"id": 10,
"firstName": "Isaac",
"last_name": "Newton",
"age": 84
}
"""
loaded = Person.model_validate_json(data_json)
print(loaded)
# Person(id_=10, first_name='Isaac', last_name='Newton', age=84)
# シリアライズ(エイリアスなし vs. エイリアスあり)
print(loaded.model_dump())
# {'id_': 10, 'first_name': 'Isaac', 'last_name': 'Newton', 'age': 84}
print(loaded.model_dump(by_alias=True))
# {'id': 10, 'firstName': 'Isaac', 'lastName': 'Newton', 'age': 84}
ポイントまとめ
Plain Alias(通常の alias)
フィールドの `alias="..."` で宣言
デシリアライズで使われる(ただし validation alias があればそちらが優先)
シリアライズで `model_dump(by_alias=True)` を呼ぶときも、`serialization_alias` がなければこの alias が使われる
Serialization Alias
`serialization_alias="..."` で宣言
`by_alias=True` でシリアライズするときにのみ使用
入力データには影響せず、出力(API応答など)専用
`populate_by_name=True`
モデル設定 `model_config` 内で指定
デシリアライズ時にエイリアスだけでなくフィールド名でも入力を受け付ける
自動エイリアス (`alias_generator`)
モデルレベルで関数をセットすると、各フィールド名を関数に通してエイリアスが決まる
個別のフィールドで `Field(alias="...")` と書けば上書き可能
`Field` によるデフォルト + エイリアス
エイリアスを設定しつつデフォルト値を与えるには `Field(alias="id", default=100)` のように一括で指定
予約語
`id` や `list` といった名前は Python では紛らわしいので `id_`, `list_` とするのが一般的
JSON のキーとしては `id`, `list` のままで、Pydantic 側のエイリアスを活用する
こうした機能を組み合わせることで、外部サービスからの JSON と自分の Python コードの間で煩雑なフィールド名をすっきり整理し、可読性を保ちながらデータを流通させることができます。Pydantic のエイリアス設定を上手く使えば、外部フォーマットをそのまま受け取りつつ、Python では整然とした型付きモデルを活用し、さらには自分の API からはより望ましいフォーマットで出力することが可能になります。