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

如何递归遍历Pydantic模型并对字符串字段执行预处理?

递归预处理Pydantic模型及嵌套结构的解决方案

原代码存在的问题

  1. 函数未添加返回语句,调用后会返回None而非处理后的对象
  2. 遍历Pydantic模型的方式错误,直接迭代模型实例会获取到非业务字段的属性
  3. 参数类型注解过于严格,无法处理字符串、列表等非BaseModel类型
  4. 可迭代对象的处理逻辑不完善,未考虑容器内的字符串元素,且未区分可变/不可变容器

修正后的代码

from collections.abc import Iterable
from pydantic import BaseModel
from typing import Any

def _remove_html_tag(s: str) -> str:
    # 替换为你的实际预处理逻辑
    return s.replace("<", "").replace(">", "")

def preprocess_item(item: Any) -> Any:
    # 处理字符串:直接应用预处理函数
    if isinstance(item, str):
        return _remove_html_tag(item)
    
    # 处理Pydantic模型:递归处理每个字段
    elif isinstance(item, BaseModel):
        for field_name in item.model_fields:
            field_value = getattr(item, field_name)
            processed_value = preprocess_item(field_value)
            setattr(item, field_name, processed_value)
        return item
    
    # 处理可迭代对象(排除字符串、字节串,避免重复处理)
    elif isinstance(item, Iterable) and not isinstance(item, (str, bytes)):
        # 处理可变容器(如列表):直接修改内部元素
        if isinstance(item, list):
            for i in range(len(item)):
                item[i] = preprocess_item(item[i])
            return item
        # 处理不可变容器(如元组):返回新的处理后的容器
        elif isinstance(item, tuple):
            return tuple(preprocess_item(elem) for elem in item)
        # 其他可迭代类型(如集合)可按需扩展
        else:
            return item
    
    # 非字符串、非模型、非可迭代的类型(如int、float)直接返回
    else:
        return item

关键修改说明

  • 返回值处理:每个分支都返回处理后的对象,确保递归调用能传递处理结果,顶层调用可直接获取修改后的模型
  • 模型字段遍历:使用model_fields获取模型定义的所有字段,避免遍历到模型的私有属性
  • 类型泛化:将参数类型改为Any,支持处理字符串、列表、元组等多种嵌套类型
  • 可迭代对象区分:针对可变(列表)和不可变(元组)容器分别处理,保证修改生效的同时兼顾不可变类型的特性
  • 字符串单独处理:直接对字符串应用预处理逻辑,无需递归调用

使用示例

# 定义你的模型
class OtherModel(BaseModel):
    other_id: int
    some_name: str

class DummyModel(BaseModel):
    location_id: int
    other_models: list[OtherModel]
    name: str
    surname: str
    one_other_model: OtherModel

# 创建测试实例
test_data = DummyModel(
    location_id=1,
    other_models=[
        OtherModel(other_id=2, some_name="<b>Apple</b>"),
        OtherModel(other_id=3, some_name="<i>Banana</i>")
    ],
    name="<div>Alice</div>",
    surname="<span>Smith</span>",
    one_other_model=OtherModel(other_id=4, some_name="<u>Cherry</u>")
)

# 执行预处理
processed_data = preprocess_item(test_data)

# 验证结果
print(processed_data.name)  # 输出: Alice
print(processed_data.one_other_model.some_name)  # 输出: Cherry
print(processed_data.other_models[1].some_name)  # 输出: Banana

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 17:25:19