JsonSerializable嵌套类创建空shell实例报类型转换错误如何解决
问题原因
类型转换异常来自两点:
- 你给序列化类写的是强制位置参数构造函数,json_serializable反序列化遇到缺失字段时会尝试传入null,和非可选参数的类型声明冲突
- 嵌套类初始化没有做分层兜底,手动传null构造嵌套对象时,生成的序列化代码会尝试把null强转成对应嵌套类型,直接触发cast错误
修复实现
1. 调整所有序列化类的构造形式
所有参与json序列化的类全部改用可选命名参数,通过初始化列表给嵌套字段设置默认空实例,同时统一提供empty构造方法生成全null空壳:
import 'package:json_annotation/json_annotation.dart'; // 修改后执行代码生成命令:flutter pub run build_runner build --delete-conflicting-outputs part 'telemetry.g.dart'; @JsonSerializable(explicitToJson: true, includeIfNull: true) class SystemTelemetry{ // 可选命名参数,所有字段可空、非必填 SystemTelemetry({ this.a, this.b, this.c, }); @JsonKey(includeIfNull: true) String? a; int? b; int? c; factory SystemTelemetry.fromJson(Map<String, dynamic> json) => _$SystemTelemetryFromJson(json); Map<String, dynamic> toJson() => _$SystemTelemetryToJson(this); // 空壳实例工厂 factory SystemTelemetry.empty() => SystemTelemetry(); } @JsonSerializable(explicitToJson: true, includeIfNull: true) class TelemetryData { // 嵌套字段用可选参数接收,未传值时默认初始化空壳 TelemetryData({ SystemTelemetry? systemTelemetry, }) : systemTelemetry = systemTelemetry ?? SystemTelemetry.empty(); @JsonKey(includeIfNull: true) SystemTelemetry systemTelemetry; factory TelemetryData.fromJson(Map<String, dynamic> json) => _$TelemetryDataFromJson(json); Map<String, dynamic> toJson() => _$TelemetryDataToJson(this); // 顶层空壳实例工厂 factory TelemetryData.empty() => TelemetryData(); }
2. 全局容器类初始化
Common类中的静态变量直接调用空壳工厂初始化,不需要用late延迟初始化,避免未初始化访问问题:
class Common { // 跨页面共享的全局 telemetry 存储 static TelemetryData telemetryData = TelemetryData.empty(); // 其余全局方法、属性保持原有逻辑不变 }
3. 使用说明
- 字段赋值逻辑不需要改动,原有访问写法完全兼容:
Common.telemetryData.systemTelemetry.a = data[0];
- 导出JSON时直接调用
Common.telemetryData.toJson()即可,所有未赋值的字段(包括嵌套类内部的字段)都会按要求输出null,不会出现字段缺失 - 导入JSON时直接调用
TelemetryData.fromJson(jsonMap)即可,哪怕JSON文件中缺失部分嵌套字段,构造函数的默认空实例兜底也不会触发类型转换错误
注意事项
- 每次修改序列化类的字段、构造函数后,必须重新执行build_runner代码生成命令,否则旧的生成代码会持续触发类型错误
- 只要是需要输出null值的可空字段,不要在构造函数中设置非null的默认值,保持字段初始状态为null即可
- 多层嵌套的场景下,每一层嵌套类都要实现自己的empty空壳工厂,上一层初始化时默认调用下一层的empty方法,就能实现全链路的空壳初始化
内容的提问来源于stack exchange,提问作者EN20
相关产品推荐
相关产品推荐

