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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 11:33:14