Pydanic动态别名生成器支持



我需要在pydantic模型中支持动态别名(如果可能的话)。

对于JSON数据:

{
"Time Series (5min)": {
"A": 1,
"B": 2
}
}

我在这里有一个pydantic类:

from pydantic import BaseModel, Field
class IntraDayQuote(BaseModel):
data: Optional[dict] = Field({}, alias='Time Series (5min)')

解析正确,但我想忽略"(5min)"字段名的一部分,如:

from pydantic import BaseModel, Field
class IntraDayQuote(BaseModel):
data: Optional[dict] = Field({}, alias='Time Series .*')

pydantic可以做到吗?我尝试了别名alias_generator从文档,但没有运气:

def convert_field_names_for_alias(field_name):
print(f"field name conversion: {field_name}")
new_field_name = field_name
if field_name.startswith("Time Series ("):
new_field_name = "data"
return new_field_name
class IntraDayQuote(BaseModel):
data: Optional[dict]
class Config:   
alias_generator = convert_field_names_for_alias
allow_population_by_field_name = True

您可以直接插入一个过滤器函数,如下所示:

import json
import pydantic
# I've made some assumptions about the format of your data here,
# since the example you included in your question was invalid.
json_data = """
{
"Time Series (5 min)": {
"a": 1,
"b": 2
}
}
"""

class IntraDayQuote(pydantic.BaseModel):
data: dict | None

def normalize_fields(d):
return {"data" if k.startswith("Time Series (") else k: v for k, v in d.items()}

q = IntraDayQuote(**normalize_fields(json.loads(json_data)))
print(repr(q))

这个输出:

IntraDayQuote(data={'a': 1, 'b': 2})

正如@scolvin在评论中建议的那样,我们实际上可以使normalize_fields成为根验证器,它看起来像这样:

import json
import pydantic
json_data = """
{
"Time Series (5 min)": {
"a": 1,
"b": 2
}
}
"""

class IntraDayQuote(pydantic.BaseModel):
data: dict | None
@pydantic.root_validator(pre=True)
def normalize_fields(cls, values):
return {
"data" if k.startswith("Time Series (") else k: v for k, v in values.items()
}

q = IntraDayQuote(**json.loads(json_data))
print(repr(q))

这样比较干净。