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

自定义JsonConverter编译后对fromJson无效问题排查

问题:自定义JsonConverter未生效,反序列化空数组meta字段报错

我尝试为类中的特定字段创建自定义JsonConverter,原因是调用的API返回的meta字段可能是字典或空数组,但需要始终保存为Map<String, dynamic>。但执行flutter pub run build_runner build后,生成的代码未使用自定义转换器,反序列化meta为空数组的JSON时触发错误。

原代码

Tag类及自定义Converter

import 'package:json_annotation/json_annotation.dart';

part 'tag.g.dart';

@JsonSerializable()
class Tag {
  int? id;
  int? count;
  String? description;
  Uri? link;
  String? name;
  String? slug; 
  String? taxonomy;
  @EmptyMetaToMapConverter()
  Map<String, dynamic>? meta;

  Tag();

  factory Tag.fromJson(Map<String, dynamic> json) => _$TagFromJson(json);
  Map<String, dynamic> toJson() => _$TagToJson(this);
}

class EmptyMetaToMapConverter extends JsonConverter<Map, Object?> {
  const EmptyMetaToMapConverter();

  @override
  Map<String, dynamic> fromJson(Object? json) {
    if (json is List) return {};
    if (json is Map<String, dynamic>) return json;

    throw Exception();
  }

  @override
  Map toJson(Map object) => object;
}

生成的tag.g.dart关键部分

// ...
Tag _$TagFromJson(Map<String, dynamic> json) => Tag()
  // ...其他字段解析
  ..meta = json['meta'] as Map<String, dynamic>?; // 自定义Converter未生效
// ...

环境信息

  • Flutter版本:3.16.8
  • 依赖版本:
json_serializable: ^6.7.1
build_runner: ^2.4.8
json_annotation: ^4.8.1

问题原因

自定义Converter的泛型参数与字段类型不匹配:

  • 字段meta的类型是Map<String, dynamic>?(可空),但Converter定义为JsonConverter<Map, Object?>,泛型中的Map是非空类型,导致json_serializable无法识别该转换器适用于这个可空字段。
  • 另外fromJson返回的Map<String, dynamic>与Converter泛型的Map也存在精度不匹配问题。

修正方案

调整自定义Converter的泛型参数,使其与字段类型完全匹配,同时完善空值处理:

修正后的Converter和Tag类

import 'package:json_annotation/json_annotation.dart';

part 'tag.g.dart';

@JsonSerializable()
class Tag {
  int? id;
  int? count;
  String? description;
  Uri? link;
  String? name;
  String? slug; 
  String? taxonomy;
  @EmptyMetaToMapConverter()
  Map<String, dynamic>? meta;

  Tag();

  factory Tag.fromJson(Map<String, dynamic> json) => _$TagFromJson(json);
  Map<String, dynamic> toJson() => _$TagToJson(this);
}

// 泛型改为与字段匹配的Map<String, dynamic>? 和 Object?
class EmptyMetaToMapConverter extends JsonConverter<Map<String, dynamic>?, Object?> {
  const EmptyMetaToMapConverter();

  @override
  Map<String, dynamic>? fromJson(Object? json) {
    if (json == null) return null; // 处理null情况
    if (json is List) return {}; // 空数组转为空Map
    if (json is Map<String, dynamic>) return json; // 直接返回字典

    throw Exception('Unsupported type for meta field: ${json.runtimeType}');
  }

  @override
  Map<String, dynamic>? toJson(Map<String, dynamic>? object) => object; // 适配可空类型
}

重新生成代码

执行以下命令重新生成序列化代码:

flutter pub run build_runner build --delete-conflicting-outputs

生成后的tag.g.dart中,meta字段会正确调用转换器:

// ...
Tag _$TagFromJson(Map<String, dynamic> json) => Tag()
  // ...其他字段解析
  ..meta = const EmptyMetaToMapConverter().fromJson(json['meta']);
// ...

这样就能正确处理meta字段为字典、空数组或null的情况,避免反序列化报错。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 20:55:33