らくがきちょう

なんとなく ~所属組織/団体とは無関係であり、個人の見解です~

Python で「ハイフンを含んだデータ名」の JSON を pydantic で受け取る場合の処理

Python で「JSON でデータを受け取る」ようなケースを考えた場合、データを pydantic でクラス化するケースがあると思います。 例えば FastAPI で POST された JSON を受け取る Web アプリケーションを開発する場合などです。 こういった場合、「JSON 内のデータ名」と「クラスの変数名」は同じ名前にするのが自然だと思います。 しかし、- を含む JSON を渡された場合、どういって処理するのか、メモしておきたいと思います。

1. 記号を含まないデータ名の場合

記号を含まない場合は特に処理を意識する必要がありません。 下記のサンプルでは「渡されるデータ名 → 受け取るデータ名」が「hostnamehostname」で一致しており、記号なども含んでいない為、特別な処理は不要です。

from pydantic import BaseModel

class Device(BaseModel):
    hostname: str

external_data = {'hostname': 'RouterA'}
data = Device(**external_data)
print(data)

実行結果は以下の通りです。

$ python sample1.py
hostname='RouterA'

2. データ名に「アンダースコア」を含む場合

データ名に _ (アンダースコア) を含む場合も、特に考慮はありません。 下記のサンプルでは「host_namehost_name」で一致しており、特別な処理は不要です。

from pydantic import BaseModel

class Device(BaseModel):
    host_name: str

external_data = {'host_name': 'RouterA'}
data = Device(**external_data)
print(data)

実行結果は以下の通りです。

$ python sample2.py
host_name='RouterA'

3. データ名に「ハイフン」を含む場合

データに - (ハイフン) を含む場合は問題があります。

from pydantic import BaseModel

class Device(BaseModel):
    host-name: str  # Error!

external_data = {'host-name': 'RouterA'}
data = Device(**external_data)
print(data)

実行結果は以下の通りです。 変数名に Python で理解出来ない - を含んでいる為、エラーになります。

$ python sample3.py
  File "sample3.py", line 4
    host-name: str  # Error!
    ^
SyntaxError: illegal target for annotation

4. データ名の「ハイフン」を Alias で回避する

このエラーを回避するには変数名自体は host_name のようにアンダースコアを使うものの、alias を設定してデータ内の host-name というハイフンを含む名前を受け取れるようにします。

from pydantic import BaseModel, Field

class Device(BaseModel):
    host_name: str  = Field(..., alias='host-name')

external_data = {'host-name': 'RouterA'}
data = Device(**external_data)
print(data)

これでプログラム内部でアクセスする場合は host_name とアンダースコア形式ではあるものの、データを受け取る処理自体は host-name という alias が使えるようになりました。

$ python sample4.py
host_name='RouterA'