You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Pydantic定义动态泛型基类处理Intercom列表模型?

实现泛型Pydantic基类统一处理Intercom列表结构

解决方案思路

Intercom的列表结构有固定模式:包含type字段(格式为{资源单数}.list)和一个与外层键同名的资源列表字段。我们可以通过泛型+元类实现动态生成字段和自动验证,无需重复定义每个列表模型。

完整代码实现

1. 导入依赖

from typing import Generic, TypeVar, List, Type
from pydantic import BaseModel, validator, Field
from pydantic._internal._model_construction import ModelMetaclass

2. 定义泛型基类与元类

T = TypeVar('T')

class BaseListMeta(ModelMetaclass, Generic[T]):
    def __new__(cls, name, bases, namespace, **kwargs):
        # 获取泛型参数(列表中的元素类型)
        item_type = kwargs.get('__parameters__', (None,))[0]
        if item_type is not None:
            # 优先使用元素类自定义的资源名称,否则自动推断
            if hasattr(item_type, '__resource_name__'):
                resource_singular = item_type.__resource_name__
            else:
                resource_singular = item_type.__name__.lower()
            resource_plural = f"{resource_singular}s"
            
            # 动态添加资源列表字段
            namespace[resource_plural] = Field(..., annotation=List[item_type])
            
            # 动态生成type字段的验证器
            def validate_type(cls, v):
                expected_type = f"{resource_singular}.list"
                if v != expected_type:
                    raise ValueError(f"Type must be '{expected_type}'")
                return v
            namespace['validate_type'] = validator('type')(validate_type)
        
        return super().__new__(cls, name, bases, namespace, **kwargs)

class BaseList(BaseModel, Generic[T], metaclass=BaseListMeta):
    type: str
    
    class Config:
        extra = 'forbid'  # 禁止多余字段,保证结构严格符合Intercom规范

3. 定义元素模型

class Contact(BaseModel):
    id: str
    name: str

# 处理不规则复数的示例(如person -> people)
class Person(BaseModel):
    __resource_name__ = "person"  # 手动指定资源单数名称
    id: str
    name: str

4. 在父模型中使用

class ParentModel(BaseModel):
    contacts: BaseList[Contact]
    people: BaseList[Person]

验证示例

# 符合规范的测试数据
test_data = {
    "contacts": {
        "type": "contact.list",
        "contacts": [
            {"id": "1", "name": "Alice"},
            {"id": "2", "name": "Bob"}
        ]
    },
    "people": {
        "type": "person.list",
        "people": [
            {"id": "3", "name": "Charlie"},
            {"id": "4", "name": "Diana"}
        ]
    }
}

# 实例化模型
model = ParentModel(**test_data)
print(model.contacts.contacts[0].name)  # 输出: Alice
print(model.people.people[0].name)     # 输出: Charlie

# 错误测试(type不符合规范)
bad_data = {
    "contacts": {
        "type": "contact.lists",  # 错误的type
        "contacts": [{"id": "1", "name": "Alice"}]
    }
}
# 会抛出ValidationError: 1 validation error for ParentModel -> contacts -> type
# Value must be 'contact.list'

关键说明

  • 动态字段生成:元类会根据泛型参数(元素类型)自动生成对应的列表字段(如Contact对应contacts)。
  • 自动类型验证:验证器会自动检查type字段是否符合{资源单数}.list的格式。
  • 不规则复数支持:通过在元素类中定义__resource_name__属性,可以手动指定资源单数名称,处理如person/people这类不规则复数。

内容的提问来源于stack exchange,提问作者JohnDu17

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 13:50:24