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

如何为顶层Freezed模型指定自定义JsonConverter解决反序列化报错?

问题原因

你当前使用的是Freezed的联合类型(Sealed Union) 特性,Freezed默认生成的顶层fromJson方法会强制读取JSON中的runtimeType字段,以此判断应该实例化哪一个子类构造器(Data/Loading/Error)。由于后端返回的JSON没有该字段,因此会抛出类型校验异常,哪怕传入空Map也会因为找不到runtimeType匹配项报错。

解决方案

方案1:直接调用对应构造器(最适配当前场景)

你当前的接口请求成功场景固定对应Data构造器,完全不需要走Freezed自动生成的联合类型判断逻辑,直接修改api_provider中的代码即可:

return result.when(
  // 成功场景直接构造Data实例,无参数时可以加const优化性能
  (json) => const InitialDataModel.Data(),
  error: (e) => InitialDataModel.error(e),
);

如果后续Data构造器需要添加字段,你可以为单构造器单独配置fromJson,调整后代码如下:

// 模型定义修改示例
@freezed
class InitialDataModel with _$InitialDataModel {
  const factory InitialDataModel({
    // 新增需要反序列化的字段
    String? userToken,
    int? expireTime,
  }) = Data;

  const factory InitialDataModel.loading() = Loading;
  const factory InitialDataModel.error([String? message]) = Error;

  // 只给Data构造器加fromJson即可
  factory Data.fromJson(Map<String, dynamic> json) => _$DataFromJson(json);
}

// api_provider调用示例
(json) => Data.fromJson(json),

方案2:自定义联合类型反序列化规则

如果你需要保留使用顶层InitialDataModel.fromJson的写法,可以通过Freezed注解自定义反序列化逻辑:

场景A:后端有状态区分字段

如果后端返回的JSON中有专门用来区分状态的字段(比如code、type),可以通过unionKey指定匹配字段,unionValue指定每个构造器对应的值:

@Freezed(unionKey: 'code') // 指定用code字段匹配构造器
class InitialDataModel with _$InitialDataModel {
  @JsonValue(200) // code为200时匹配Data构造
  const factory InitialDataModel() = Data;

  @JsonValue(-1) // code为-1时匹配Error构造
  const factory InitialDataModel.error([String? message]) = Error;

  const factory InitialDataModel.loading() = Loading;

  factory InitialDataModel.fromJson(Map<String, dynamic> json) => _$InitialDataModelFromJson(json);
}

场景B:后端无状态区分字段,指定默认构造

如果后端没有状态区分字段,可指定默认构造器作为未知状态的 fallback:

@Freezed(unknownEnumValue: InitialDataModel.Data) // 未匹配到类型时默认返回Data
class InitialDataModel with _$InitialDataModel {
  const factory InitialDataModel() = Data;
  const factory InitialDataModel.loading() = Loading;
  const factory InitialDataModel.error([String? message]) = Error;

  factory InitialDataModel.fromJson(Map<String, dynamic> json) => _$InitialDataModelFromJson(json);
}

方案3:完全自定义fromJson逻辑

你也可以直接重写顶层fromJson方法,完全自己控制反序列化规则,完全不需要依赖Freezed的默认匹配逻辑:

@freezed
class InitialDataModel with _$InitialDataModel {
  const factory InitialDataModel() = Data;
  const factory InitialDataModel.loading() = Loading;
  const factory InitialDataModel.error([String? message]) = Error;

  factory InitialDataModel.fromJson(Map<String, dynamic> json) {
    // 自定义判断逻辑,比如判断是否有报错字段
    if (json.containsKey('error_msg')) {
      return InitialDataModel.error(json['error_msg']);
    }
    // 默认返回Data
    return const InitialDataModel();
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 13:24:04