Pydanic动态别名发电机支持

发布于 2025-02-06 18:23:40 字数 1060 浏览 2 评论 0原文

我需要支持我的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)')

正确解析,但是我想忽略“(5分钟)”字段名称的“(5分钟)”,例如:

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

这是可以用Pydantic实现的吗?我尝试了Docs的Alias 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

I need to support dynamic aliases in my pydantic model (if this is possible).

For this JSON data:

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

I have a pydantic class here:

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

This parses correctly, BUT i want to ignore the "(5min)" part of the field name like so:

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

Is this achieveable with pydantic? I tried alias alias_generator from the docs but no luck:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

深海蓝天 2025-02-13 18:23:40

您可以只插入过滤器函数,例如这样:

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))

有点清洁。

You could just interpose a filter function, like this:

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))

This outputs:

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

As @scolvin suggested in the comments, we could actually make normalize_fields a root validator, which would look like this:

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))

That's a little cleaner.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文