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

使用Pydantic解析JSON报错:'NoneType' object is not subscriptable

问题分析与解决方案

核心错误原因

你遇到的'NoneType' object is not subscriptable错误,根源在于**ImportInModel中的两个root_validator函数没有返回处理后的values字典**。Pydantic的根验证器需要返回修改后的(或原封不动的)values对象,否则验证流程会得到None,后续尝试访问None['type']这类操作就会触发类型错误。

另外,ImportsInModel中的check_parent验证逻辑也存在问题,当前的两两循环断言会导致测试数据直接失败,需要调整逻辑。

修正后的代码

1. 修复ImportInModel的根验证器

给每个root_validator添加返回值:

from enum import Enum
from pydantic import BaseModel, constr, PositiveInt, root_validator, validator, ValidationError
from datetime import datetime
import ujson

class FileTypeEnum(str, Enum):
    file = 'FILE'
    folder = 'FOLDER'

class ImportInModel(BaseModel):
    id: constr(min_length=1)
    url: constr(max_length=255) | None = None
    parentId: str | None = None
    size: PositiveInt | None = None
    type: FileTypeEnum

    @root_validator
    def check_url(cls, values: dict):
        file_type = values['type']
        file_url = values.get('url')
        if file_type == FileTypeEnum.folder and file_url is not None:
            raise ValueError(
                f"{file_type}'s type item should not have a url!"
            )
        # 必须返回values,否则后续处理会拿到None
        return values

    @root_validator
    def check_size(cls, values: dict):
        file_type = values['type']
        file_size = values.get('size')
        if file_type == FileTypeEnum.file and file_size is None:
            raise ValueError(
                f"{file_type}'s type item must have a size!"
            )
        # 必须返回values
        return values

2. 修复ImportsInModel的父节点验证逻辑

原逻辑会遍历所有item两两对比,只要有一对不满足断言就报错,这不符合实际需求。正确的逻辑应该是:所有文件类型的item,其parentId必须对应列表中存在的文件夹类型item。

class ImportsInModel(BaseModel):
    items: list[ImportInModel]
    updateDate: datetime

    class Config:
        json_encoders = {
            datetime: lambda dt: dt.isoformat()
        }
        json_loads = ujson.loads

    @validator('items')
    def check_parent_valid(cls, v):
        # 先收集所有文件夹的id
        folder_ids = {item.id for item in v if item.type == FileTypeEnum.folder}
        for item in v:
            if item.type == FileTypeEnum.file:
                # 文件必须有parentId,且parentId对应存在的文件夹
                if item.parentId is None:
                    raise ValueError(f"File {item.id} must have a parentId")
                if item.parentId not in folder_ids:
                    raise ValueError(f"File {item.id}'s parent {item.parentId} is not a valid folder")
        return v

3. 测试修正后的代码

测试数据需要补充对应的文件夹item,否则父节点验证会失败:

try:
    json_raw = '''{
        "items": [
            {
                "id": "элемент_1_1",
                "parentId": null,
                "size": null,
                "type": "FOLDER"
            },
            {
                "id": "элемент_1_4",
                "url": "/file/url1",
                "parentId": "элемент_1_1",
                "size": 234,
                "type": "FILE"
            }
        ],
        "updateDate": "2022-05-28T21:12:01.000Z"
    }'''
    result = ImportsInModel.parse_raw(json_raw)
    print("验证成功:", result)
except ValidationError as e:
    print(e)

关键注意事项

  • 根验证器(root_validator)必须返回values,否则会导致后续处理拿到None值。
  • 验证逻辑要贴合实际业务需求,避免无意义的全量两两对比。
  • 使用values.get(key)代替直接values[key]可以避免部分字段未被验证时的KeyError(防御性写法)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 05:10:16