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

Python数据类转换时strptime()参数错误排查:JSON转类型化对象列表失败

Python数据类转换时strptime()参数错误排查:JSON转类型化对象列表失败

我太懂这种踩坑的感觉了——好不容易把数据类字段和JSON结构一一对应好,结果卡在strptime的None值错误上,简直头疼。咱们先把问题拆解开,一步步解决。

问题根源定位

你虽然给可选日期字段加了Optional[DateTimePattern[...]],但dataclass-wizard的DateTimePattern类型在处理None值时,内部逻辑还是会尝试把None传给strptime方法,而strptime只接受字符串参数,自然就抛出类型错误了。说白了就是:Optional标记告诉Python这个字段可以是None,但DateTimePattern的解析器没跟上这个逻辑,还是硬要解析None值。

另外,我注意到你贴的第二条JSON记录最后last_analytics_received_at字段是截断的,记得先确保所有JSON数据是完整有效的,不然还没到日期解析步骤可能就先报错了。

具体解决方法

1. 先升级依赖(最快速的尝试)

dataclass-wizard的老版本对Optional[DateTimePattern]的支持确实有bug,先把包更到最新版,大概率能直接解决问题:

pip install --upgrade dataclass-wizard

2. 调整数据类字段定义(更稳妥的方案)

如果升级后还是不行,咱们换个思路:用原生的datetime类型代替DateTimePattern,配合JSONWizard的全局日期格式配置,这样解析器会自动处理None值。修改后的字段定义如下:

from dataclasses import dataclass
from dataclass_wizard import fromlist, JSONWizard
from datetime import datetime
from typing import Optional

@dataclass
class FotaDevice(JSONWizard):
    imei:int 
    serial:int 
    model:str 
    spec_id:int 
    platform_id:int 
    current_configuration:Optional[str]
    current_firmware:str 
    description:Optional[str]
    company_id:int 
    group_id:Optional[int]
    track:int 
    # 把所有Optional[DateTimePattern]换成Optional[datetime]
    first_login:Optional[datetime] = None
    seen_at:Optional[datetime] = None
    created_at:datetime
    updated_at:Optional[datetime] = None
    state_timestamp:Optional[datetime] = None
    created_by:int 
    updated_by:Optional[int]
    chip_id:Optional[int]
    gsm_number:Optional[str]
    gnss_version:Optional[str]
    login_count:int 
    parameter_collect:Optional[str]
    last_sync:datetime
    iccid:str 
    imsi:str 
    ble_firmware:Optional[str]  # 注意:JSON里该字段为null,之前的str类型会报错
    sold_at:datetime
    shipment:str 
    last_analytics_received_at:Optional[datetime] = None
    product_code:str 
    company_name:Optional[str]
    group_name:Optional[str]
    next_task:Optional[str]
    can_adapter:Optional[str]
    obd:Optional[str]
    accessories:Optional[str]
    carrier:Optional[str]
    company:Optional[dict]  # 如果你定义了FotaCompany类,这里换成Optional[FotaCompany]
    group:Optional[dict]
    activity_status:str 
    task_queue:str 
    modem_version:Optional[str]
    model_platform:str 

    # 全局配置日期格式,不用每个字段单独写
    class Meta:
        datetime_format = '%Y-%m-%d %H:%M:%S'

3. 自定义解析逻辑(终极兜底方案)

如果上面两种方法都不管用,咱们就手动接管日期解析,确保None值直接跳过:

from dataclasses import dataclass
from dataclass_wizard import fromlist, JSONWizard
from datetime import datetime
from typing import Optional

@dataclass
class FotaDevice(JSONWizard):
    # 所有字段定义和上面一致...

    @classmethod
    def from_dict(cls, data: dict):
        DATE_FORMAT = '%Y-%m-%d %H:%M:%S'
        # 处理可选日期字段:值为None就跳过,否则解析成datetime
        optional_date_fields = [
            'first_login', 'seen_at', 'updated_at', 'state_timestamp',
            'last_analytics_received_at'
        ]
        for field in optional_date_fields:
            value = data.get(field)
            if value is not None:
                data[field] = datetime.strptime(value, DATE_FORMAT)
        # 处理必填日期字段:确保一定有值,直接解析
        required_date_fields = [
            'created_at', 'last_sync', 'sold_at'
        ]
        for field in required_date_fields:
            data[field] = datetime.strptime(data[field], DATE_FORMAT)
        # 调用父类方法完成剩余字段的解析
        return super().from_dict(data)

最后验证

修改完成后,再运行你的转换代码:

result_list = fromlist(FotaDevice, intermediate_list)

记得先打印intermediate_list里的每个元素,确认所有日期字段要么是符合格式的字符串,要么是None,没有截断或格式错误的值。

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.07 10:27:59