I'm trying to convert a json array to a Python list of typed objects. It's data from Teltonika FOTA
The call result_list = fromlist(FotaDevice, intermediate_list) is failing with the error message TypeError: strptime() argument 1 must be str, not None
imports are:
from dataclasses import dataclass
from dataclass_wizard import fromlist, asdict, DateTimePattern, JSONWizard
from typing import Optional
The dataclass is as follows:
@dataclass
class FotaDevice(JSONWizard, debug=logging.DEBUG):
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
first_login:Optional[DateTimePattern['%Y-%m-%d %H:%M:%S']]
seen_at:Optional[DateTimePattern['%Y-%m-%d %H:%M:%S']]
created_at:DateTimePattern['%Y-%m-%d %H:%M:%S']
updated_at:Optional[DateTimePattern['%Y-%m-%d %H:%M:%S']]
state_timestamp:Optional[DateTimePattern['%Y-%m-%d %H:%M:%S']]
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:DateTimePattern['%Y-%m-%d %H:%M:%S']
iccid:str
imsi:str
ble_firmware:str
sold_at:DateTimePattern['%Y-%m-%d %H:%M:%S']
shipment:str
last_analytics_received_at:DateTimePattern['%Y-%m-%d %H:%M:%S']
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[FotaCompany]
group:Optional[FotaGroup]
activity_status:str
task_queue:str
modem_version:Optional[str]
model_platform:str
def __str__(self):
return f"{self.imei}:{self.model}"
Here's two records lightly sanitised from the collection so you can see the source data:
[
{
"imei": 1111111,
"serial": 111,
"model": "FMM001",
"spec_id": 1,
"platform_id": 1,
"current_configuration": null,
"current_firmware": "03.27.13.Rev.54",
"description": "xxxxxx",
"company_id": 13991,
"group_id": null,
"track": 6,
"first_login": "2022-11-09 02:08:20",
"seen_at": "2024-02-07 22:29:28",
"created_at": "2021-10-18 09:14:06",
"updated_at": "2024-02-07 22:29:28",
"state_timestamp": null,
"created_by": 10,
"updated_by": 1,
"chip_id": null,
"gsm_number": "6141111",
"gnss_version": null,
"login_count": 1,
"parameter_collect": null,
"last_sync": "2024-02-01 09:55:25",
"iccid": "8961111111111111",
"imsi": "111111111q111",
"ble_firmware": null,
"sold_at": "2021-11-10 00:00:00",
"shipment": "LTG172",
"last_analytics_received_at": null,
"product_code": "FMM001FPSP01",
"company_name": "xxxxxxxxxxx",
"group_name": null,
"next_task": null,
"can_adapter": null,
"obd": null,
"accessories": null,
"carrier": null,
"company": {
"code": "SG3414",
"id": 13991,
"name": "xxxxxxxxxx",
"company_id": 37,
"deleted_at": null,
"created_at": "2021-02-16 03:57:26",
"updated_at": "2023-06-12 09:21:35",
"created_by": 1,
"updated_by": 11239
},
"group": null,
"activity_status": "Offline",
"task_queue": "Empty",
"modem_version": null,
"model_platform": "Fmx"
},
{
"imei": 2222222222,
"serial": 2222,
"model": "FMM001",
"spec_id": 1,
"platform_id": 1,
"current_configuration": null,
"current_firmware": "03.27.07.Rev.00",
"description": "xxxxxxx",
"company_id": 13991,
"group_id": null,
"track": 6,
"first_login": "2022-11-09 01:56:02",
"seen_at": "2023-02-22 01:00:37",
"created_at": "2021-10-18 09:14:06",
"updated_at": "2023-09-18 02:18:18",
"state_timestamp": null,
"created_by": 10,
"updated_by": 8225,
"chip_id": null,
"gsm_number": "61473914722",
"gnss_version": null,
"login_count": 1,
"parameter_collect": null,
"last_sync": "2023-02-02 04:22:21",
"iccid": "89622222222222",
"imsi": "2222222222",
"ble_firmware": null,
"sold_at": "2021-11-10 00:00:00",
"shipment": "LTG172",
"last_analytics_received_at": null,
"product_code": "FMM001FPSP01",
"company_name": "xxxxxxx",
"group_name": null,
"next_task": null,
"can_adapter": null,
"obd": null,
"accessories": null,
"carrier": null,
"company": {
"code": "SG3414",
"id": 13991,
"name": "xxxxxxx",
"company_id": 37,
"deleted_at": null,
"created_at": "2021-02-16 03:57:26",
"updated_at": "2023-06-12 09:21:35",
"created_by": 1,
"updated_by": 11239
},
"group": null,
"activity_status": "Offline",
"task_queue": "Empty",
"modem_version": null,
"model_platform": "Fmx"
},
]
Logically the error is on a datetime field, which is why I've wrapped them as Optional
I've added debugging to the class header, and I don't understand the output. It seems to imply that every field has a missing type? Newlines on Field( added by me:
DEBUG:dataclass_wizard:Globals before function compilation: {'cls_fields': (
Field(name='imei',type=<class 'int'>,default=<dataclasses._MISSING_TYPE object at 0x000001507F56E180>,default_factory=<dataclasses._MISSING_TYPE object at 0x000001507F56E180>,init=True,repr=True,hash=None,compare=True,metadata=mappingproxy({}),kw_only=False,_field_type=_FIELD),
Field(name='serial',type=<class 'int'>,default=<dataclasses._MISSING_TYPE object at 0x000001507F56E180>,default_factory=<dataclasses._MISSING_TYPE object at 0x000001507F56E180>,init=True,repr=True,hash=None,compare=True,metadata=mappingproxy({}),kw_only=False,_field_type=_FIELD),
Field(name='model',type=<class 'str'>,default=<dataclasses._MISSING_TYPE object at 0x000001507F56E180>,default_factory=<dataclasses._MISSING_TYPE object at 0x000001507F56E180>,init=True,repr=True,hash=None,compare=True,metadata=mappingproxy({}),kw_only=False,_field_type=_FIELD),
Field(name='spec_id',type=<class 'int'>,default=<dataclasses._MISSING_TYPE object at 0x000001507F56E180>,default_factory=<dataclasses._MISSING_TYPE object at 0x000001507F56E180>,init=True,repr=True,hash=None,compare=True,metadata=mappingproxy({}),kw_only=False,_field_type=_FIELD),
Field(name='platform_id',type=<class 'int'>,default=<dataclasses._MISSING_TYPE object at 0x000001507F56E180>,default_factory=<dataclasses._MISSING_TYPE object at 0x000001507F56E180>,init=True,repr=True,hash=None,compare=True,metadata=mappingproxy({}),kw_only=False,_field_type=_FIELD),
Field(name='current_configuration',type=typing.Optional[str],default=<dataclasses._MISSING_TYPE object at 0x000001507F56E180>,default_factory=<dataclasses._MISSING_TYPE object at 0x000001507F56E180>,init=True,repr=True,hash=None,compare=True,metadata=mappingproxy({}),kw_only=False,_field_type=_FIELD),
Field(name='current_firmware',type=<class 'str'>,default=<dataclasses._MISSING_TYPE object at 0x000001507F56E180>,default_factory=<dataclasses._MISSING_TYPE object at 0x000001507F56E180>,init=True,repr=True,hash=None,compare=True,metadata=mappingproxy({}),kw_only=False,_field_type=_FIELD),
Field(name='description',type=typing.Optional[str],default=<dataclasses._MISSING_TYPE object at 0x000001507F56E180>,default_factory=<dataclasses._MISSING_TYPE object at 0x000001507F56E180>,init=True,repr=True,hash=None,compare=True,metadata=mappingproxy({}),kw_only=False,_field_type=_FIELD),
Field(name='company_id',type=<class 'int'>,default=<dataclasses._MISSING_TYPE object at 0x000001507F56E180>,default_factory=<dataclasses._MISSING_TYPE object at 0x000001507F56E180>,init=True,repr=True,hash=None,compare=True,metadata=mappingproxy({}),kw_only=False,_field_type=_FIELD),
Field(name='group_id',type=typing.Optional[int],default=<dataclasses._MISSING_TYPE object at 0x000001507F56E180>,default_factory=<dataclasses._MISSING_TYPE object at 0x000001507F56E180>,init=True,repr=True,hash=None,compare=True,metadata=mappingproxy({}),kw_only=False,_field_type=_FIELD),
Field(name='track',type=<class 'int'>,default=<dataclasses._MISSING_TYPE object at 0x000001507F56E180>,default_factory=<dataclasses._MISSING_TYPE object at 0x000001507F56E180>,init=True,repr=True,hash=None,compare=True,metadata=mappingproxy({}),kw_only=False,_field_type=_FIELD),
Field(name='first_login',type=typing.Optional[PatternedDT(cls=<class 'datetime.datetime'>, pattern='%Y-%m-%d %H:%M:%S')],default=<dataclasses._MISSING_TYPE object at 0x000001507F56E180>,default_factory=<dataclasses._MISSING_TYPE object at 0x000001507F56E180>,init=True,repr=True,hash=None,compare=True,metadata=mappingproxy({}),kw_only=False,_field_type=_FIELD),
Field(name='seen_at',type=typing.Optional[PatternedDT(cls=<class 'datetime.datetime'>, pattern='%Y-%m-%d %H:%M:%S')],default=<dataclasses._MISSING_TYPE object at 0x000001507F56E180>,default_factory=<dataclasses._MISSING_TYPE object at 0x000001507F56E180>,init=True,repr=True,hash=None,compare=True,metadata=mappingproxy({}),kw_only=False,_field_type=_FIELD),
Field(name='created_at',type=PatternedDT(cls=<class 'datetime.datetime'>, pattern='%Y-%m-%d %H:%M:%S'),default=<dataclasses._MISSING_TYPE object at 0x000001507F56E180>,default_factory=<dataclasses._MISSING_TYPE object at 0x000001507F56E180>,init=True,repr=True,hash=None,compare=True,metadata=mappingproxy({}),kw_only=False,_field_type=_FIELD),
Field(name='updated_at',type=typing.Optional[PatternedDT(cls=<class 'datetime.datetime'>, pattern='%Y-%m-%d %H:%M:%S')],default=<dataclasses._MISSING_TYPE object at 0x000001507F56E180>,default_factory=<dataclasses._MISSING_TYPE object at 0x000001507F56E180>,init=True,repr=True,hash=None,compare=True,metadata=mappingproxy({}),kw_only=False,_field_type=_FIELD),
Field(name='state_timestamp',type=typing.Optional[PatternedDT(cls=<class 'datetime.datetime'>, pattern='%Y-%m-%d %H:%M:%S')],default=<dataclasses._MISSING_TYPE object at 0x000001507F56E180>,default_factory=<dataclasses._MISSING_TYPE object at 0x000001507F56E180>,init=True,repr=True,hash=None,compare=True,metadata=mappingproxy({}),kw_only=False,_field_type=_FIELD),
Field(name='created_by',type=<class 'int'>,default=<dataclasses._MISSING_TYPE object at 0x000001507F56E180>,default_factory=<dataclasses._MISSING_TYPE object at 0x000001507F56E180>,init=True,repr=True,hash=None,compare=True,metadata=mappingproxy({}),kw_only=False,_field_type=_FIELD),
Field(name='updated_by',type=typing.Optional[int],default=<dataclasses._MISSING_TYPE object at 0x000001507F56E180>,default_factory=<dataclasses._MISSING_TYPE object at 0x000001507F56E180>,init=True,repr=True,hash=None,compare=True,metadata=mappingproxy({}),kw_only=False,_field_type=_FIELD),
Field(name='chip_id',type=typing.Optional[int],default=<dataclasses._MISSING_TYPE object at 0x000001507F56E180>,default_factory=<dataclasses._MISSING_TYPE object at 0x000001507F56E180>,init=True,repr=True,hash=None,compare=True,metadata=mappingproxy({}),kw_only=False,_field_type=_FIELD),
Field(name='gsm_number',type=typing.Optional[str],default=<dataclasses._MISSING_TYPE object at 0x000001507F56E180>,default_factory=<dataclasses._MISSING_TYPE object at 0x000001507F56E180>,init=True,repr=True,hash=None,compare=True,metadata=mappingproxy({}),kw_only=False,_field_type=_FIELD),
Field(name='gnss_version',type=typing.Optional[str],default=<dataclasses._MISSING_TYPE object at 0x000001507F56E180>,default_factory=<dataclasses._MISSING_TYPE object at 0x000001507F56E180>,init=True,repr=True,hash=None,compare=True,metadata=mappingproxy({}),kw_only=False,_field_type=_FIELD),
Field(name='login_count',type=<class 'int'>,default=<dataclasses._MISSING_TYPE object at 0x000001507F56E180>,default_factory=<dataclasses._MISSING_TYPE object at 0x000001507F56E180>,init=True,repr=True,hash=None,compare=True,metadata=mappingproxy({}),kw_only=False,_field_type=_FIELD),
Field(name='parameter_collect',type=typing.Optional[str],default=<dataclasses._MISSING_TYPE object at 0x000001507F56E180>,default_factory=<dataclasses._MISSING_TYPE object at 0x000001507F56E180>,init=True,repr=True,hash=None,compare=True,metadata=mappingproxy({}),kw_only=False,_field_type=_FIELD),
Field(name='last_sync',type=PatternedDT(cls=<class 'datetime.datetime'>, pattern='%Y-%m-%d %H:%M:%S'),default=<dataclasses._MISSING_TYPE object at 0x000001507F56E180>,default_factory=<dataclasses._MISSING_TYPE object at 0x000001507F56E180>,init=True,repr=True,hash=None,compare=True,metadata=mappingproxy({}),kw_only=False,_field_type=_FIELD),
Field(name='iccid',type=<class 'str'>,default=<dataclasses._MISSING_TYPE object at 0x000001507F56E180>,default_factory=<dataclasses._MISSING_TYPE object at 0x000001507F56E180>,init=True,repr=True,hash=None,compare=True,metadata=mappingproxy({}),kw_only=False,_field_type=_FIELD),
Field(name='imsi',type=<class 'str'>,default=<dataclasses._MISSING_TYPE object at 0x000001507F56E180>,default_factory=<dataclasses._MISSING_TYPE object at 0x000001507F56E180>,init=True,repr=True,hash=None,compare=True,metadata=mappingproxy({}),kw_only=False,_field_type=_FIELD),
Field(name='ble_firmware',type=<class 'str'>,default=<dataclasses._MISSING_TYPE object at 0x000001507F56E180>,default_factory=<dataclasses._MISSING_TYPE object at 0x000001507F56E180>,init=True,repr=True,hash=None,compare=True,metadata=mappingproxy({}),kw_only=False,_field_type=_FIELD),
Field(name='sold_at',type=PatternedDT(cls=<class 'datetime.datetime'>, pattern='%Y-%m-%d %H:%M:%S'),default=<dataclasses._MISSING_TYPE object at 0x000001507F56E180>,default_factory=<dataclasses._MISSING_TYPE object at 0x000001507F56E180>,init=True,repr=True,hash=None,compare=True,metadata=mappingproxy({}),kw_only=False,_field_type=_FIELD),
Field(name='shipment',type=<class 'str'>,default=<dataclasses._MISSING_TYPE object at 0x000001507F56E180>,default_factory=<dataclasses._MISSING_TYPE object at 0x000001507F56E180>,init=True,repr=True,hash=None,compare=True,metadata=mappingproxy({}),kw_only=False,_field_type=_FIELD),
Field(name='last_analytics_received_at',type=PatternedDT(cls=<class 'datetime.datetime'>, pattern='%Y-%m-%d %H:%M:%S'),default=<dataclasses._MISSING_TYPE object at 0x000001507F56E180>,default_factory=<dataclasses._MISSING_TYPE object at 0x000001507F56E180>,init=True,repr=True,hash=None,compare=True,metadata=mappingproxy({}),kw_only=False,_field_type=_FIELD),
Field(name='product_code',type=<class 'str'>,default=<dataclasses._MISSING_TYPE object at 0x000001507F56E180>,default_factory=<dataclasses._MISSING_TYPE object at 0x000001507F56E180>,init=True,repr=True,hash=None,compare=True,metadata=mappingproxy({}),kw_only=False,_field_type=_FIELD),
Field(name='company_name',type=typing.Optional[str],default=<dataclasses._MISSING_TYPE object at 0x000001507F56E180>,default_factory=<dataclasses._MISSING_TYPE object at 0x000001507F56E180>,init=True,repr=True,hash=None,compare=True,metadata=mappingproxy({}),kw_only=False,_field_type=_FIELD),
Field(name='group_name',type=typing.Optional[str],default=<dataclasses._MISSING_TYPE object at 0x000001507F56E180>,default_factory=<dataclasses._MISSING_TYPE object at 0x000001507F56E180>,init=True,repr=True,hash=None,compare=True,metadata=mappingproxy({}),kw_only=False,_field_type=_FIELD),
Field(name='next_task',type=typing.Optional[str],default=<dataclasses._MISSING_TYPE object at 0x00,init=True,repr=True,hash=None,compare=True,metadata=mappingproxy({}),kw_only=False,_field_type=_FIELD),
Field(name='accessories',type=typing.Optional[str],default=<dataclasses._MISSING_TYPE object at 0x000001507F56E180>,default_factory=<dataclasses._MISSING_TYPE object at 0x000001507F56E180>,init=True,repr=True,hash=None,compare=True,metadata=mappingproxy({}),kw_only=False,_field_type=_FIELD),
Field(name='carrier',type=typing.Optional[str],default=<dataclasses._MISSING_TYPE object at 0x000001507F56E180>,default_factory=<dataclasses._MISSING_TYPE object at 0x000001507F56E180>,init=True,repr=True,hash=None,compare=True,metadata=mappingproxy({}),kw_only=False,_field_type=_FIELD),
Field(name='company',type=typing.Optional[fleetlogix.fota.FotaCompany],default=<dataclasses._MISSING_TYPE object at 0x000001507F56E180>,default_factory=<dataclasses._MISSING_TYPE object at 0x000001507F56E180>,init=True,repr=True,hash=None,compare=True,metadata=mappingproxy({}),kw_only=False,_field_type=_FIELD),
Field(name='group',type=typing.Optional[fleetlogix.fota.FotaGroup],default=<dataclasses._MISSING_TYPE object at 0x000001507F56E180>,default_factory=<dataclasses._MISSING_TYPE object at 0x000001507F56E180>,init=True,repr=True,hash=None,compare=True,metadata=mappingproxy({}),kw_only=False,_field_type=_FIELD),
Field(name='activity_status',type=<class 'str'>,default=<dataclasses._MISSING_TYPE object at 0x000001507F56E180>,default_factory=<dataclasses._MISSING_TYPE object at 0x000001507F56E180>,init=True,repr=True,hash=None,compare=True,metadata=mappingproxy({}),kw_only=False,_field_type=_FIELD),
Field(name='task_queue',type=<class 'str'>,default=<dataclasses._MISSING_TYPE object at 0x000001507F56E180>,default_factory=<dataclasses._MISSING_TYPE object at 0x000001507F56E180>,init=True,repr=True,hash=None,compare=True,metadata=mappingproxy({}),kw_only=False,_field_type=_FIELD),
Field(name='modem_version',type=typing.Optional[str],default=<dataclasses._MISSING_TYPE object at 0x000001507F56E180>,default_factory=<dataclasses._MISSING_TYPE object at 0x000001507F56E180>,init=True,repr=True,hash=None,compare=True,metadata=mappingproxy({}),kw_only=False,_field_type=_FIELD),
Field(name='model_platform',type=<class 'str'>,default=<dataclasses._MISSING_TYPE object at 0x000001507F56E180>,default_factory=<dataclasses._MISSING_TYPE object at 0x000001507F56E180>,init=True,repr=True,hash=None,compare=True,metadata=mappingproxy({}),kw_only=False,_field_type=_FIELD)), 'LOG': <Logger dataclass_wizard (DEBUG)>, 'MissingData': <class 'dataclass_wizard.errors.MissingData'>, 'MissingFields': <class 'dataclass_wizard.errors.MissingFields'>, 'ParseError': <class 'dataclass_wizard.errors.ParseError'>}
DEBUG:dataclass_wizard:Namespace after function compilation: {'cls_fromdict': <function __create_cls_fromdict_fn__.<locals>.cls_fromdict at 0x000001500106D300>}
What I'm trying to find is the definitive field causing the error
'last_analytics_received_atis described as datetime.datetime field, but gets null instead.