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

在Python与FastAPI中处理Pydantic模型的null类型partner字段报错问题

解决Pydantic模型处理null partner字段的问题

问题背景

在Python+FastAPI项目中,你编写了交易数据处理代码与Pydantic模型,test_data中某条交易的partner字段为null,尽管已在模型中将partner定义为Optional[dict] = None,但实例化AllTransaction时仍抛出错误,需要实现对null类型partner字段的正常解析。

业务代码

test_data = {
        "transactions": [{
                "id": 5494,
                "specific_wallet_id": 2079,
                "evaluation_process_transaction_id": 5229,
                "transaction_type": "Earn",
                "points": 9,
                "created_at": "2022-09-20T16:14:19.000+05:30",
                "updated_at": "2022-09-20T16:14:19.000+05:30",
                "custom_wallet_transaction_id": "null",
                "order_meta_data": {},
                "points_validity": "2023-09-20T00:00:00.000+05:30",
                "points_status": "Active",
                "transaction_amount": 450.0,
                "transaction_at": "2022-09-20T16:14:18.000+05:30",
                "tnx_status": "Successful",
                "current_points": 9,
                "programme_id": 4,
                "customer_id": 1,
                "reason_code": "Earn",
                "channel": "app",
                "order_id": "1",
                "transaction_references": "null",
                "points_value": 9.0,
                "issuer": {
                    "id": 1,
                    "name": "oo",
                    "code": "oo",
                    "image_url": "null"
                },
                "partner": null
                
            },
            {
                "id": 5486,
                "specific_wallet_id": 2079,
                "evaluation_process_transaction_id": 5221,
                "transaction_type": "Earn",
                "points": 9,
                "created_at": "2022-09-20T15:46:15.000+05:30",
                "updated_at": "2022-09-20T15:46:15.000+05:30",
                "custom_wallet_transaction_id": "null",
                "order_meta_data": {},
                "points_validity": "2023-09-20T00:00:00.000+05:30",
                "points_status": "Active",
                "transaction_amount": 450.0,
                "transaction_at": "2022-09-20T15:46:14.000+05:30",
                "tnx_status": "Successful",
                "current_points": 9,
                "programme_id": 4,
                "customer_id": 2189,
                "reason_code": "Earn",
                "channel": "app",
                "order_id": "uuu",
                "transaction_references": "null",
                "points_value": 9.0,
                "issuer": {
                    "id": 1,
                    "name": "oo",
                    "code": "ooo",
                    "image_url": "null"
                },
                "partner": {
                    "id": 1,
                    "name": "qq",
                    "code": "qq",
                    "image_url": "https://d157777v0iph40..net///offers/avis.jpg"
                }
            }
        ],
        "success": "true",
        "error": "null"
    }

results=[]
results.extend(
    [
        AllTransaction(
            issuer_id=Config.evaluation_issuer_id,
            issuer_name="",
            issuer_logo="",
            wallet_id=o["specific_wallet_id"],
            partner=o["partner"],
            points=o["points"],
            points_value_in_currency=(
                o["points"] * 1
            ),
            transaction_at=o["transaction_at"],
            transaction_id=o["id"],
            transaction_type=o["transaction_type"],
            transaction_meta={
                "order_id": o["order_id"],
                "channel": o["channel"],
                "order_meta_data": o["order_meta_data"],
            },
            transaction_name=o["transaction_type"],
        )
        for o in test_data["transactions"]
    ]
)
return TransactionResponse(results=results)

Pydantic模型代码

from typing import Optional, datetime
from pydantic import BaseModel

class TransactionDetailsPartner(BaseModel):
        partner: Optional[dict] = None
class TransactionDetails(BaseModel):
    points: int
    points_value_in_currency: float
    transaction_id: int
    transaction_at: datetime
    transaction_type: str
    transaction_meta: Optional[dict]
    transaction_name: Optional[TransactionType]
class TransactionDetailsIssuer(BaseModel):
    issuer_id: int
    issuer_name: str
    issuer_logo: str
    wallet_id: int
class AllTransaction(TransactionDetails, TransactionDetailsIssuer, TransactionDetailsPartner):
    pass

核心原因分析

报错本质是数据类型不匹配:

  • 若test_data中的null是字符串类型(比如接口返回JSON未正确解析,导致null转为字符串"null"),Pydantic无法将字符串转为dict类型,触发验证错误。
  • 直接在Python字典中写null属于语法错误,推测实际场景中是JSON解析后的字符串"null"或其他非None空值。

解决方案

方案1:预处理输入数据,统一转为Python的None

在实例化模型前,遍历交易数据,将partner字段的异常空值转为None:

for o in test_data["transactions"]:
    # 匹配所有需要转为None的情况:字符串"null"、空字典、None
    if o.get("partner") in ("null", None, {}):
        o["partner"] = None

方案2:修改Pydantic模型,添加字段验证器自动处理空值

利用Pydantic的前置验证器,在模型解析阶段自动将字符串"null"或其他空值转为None:

from pydantic import validator

class TransactionDetailsPartner(BaseModel):
    partner: Optional[dict] = None
    
    @validator('partner', pre=True)
    def convert_null_to_none(cls, value):
        # 处理字符串"null"、None、空字典
        if value == "null" or value is None or value == {}:
            return None
        return value

方案3:确保JSON数据正确解析为Python类型

如果test_data来自JSON字符串,使用json.loads()加载时,JSON中的null会自动转为Python的None,避免手动处理:

import json

# 假设原始数据是JSON格式字符串
raw_json = '{"transactions": [{"partner": null}, ...]}'
test_data = json.loads(raw_json)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 23:55:11