Dart JSON解析报错:参数类型'Id?'无法分配给参数类型'Id'如何解决
报错根因
- Dart空安全机制下,
idValues.map[json["id"]]、nameValues.map[json["name"]]两个操作的返回值是可空类型Id?、Name?,触发场景包括:JSON对应字段本身为null、字段值不在你预定义的枚举映射表中 - 但
Source类的构造参数要求传入非空的Id、Name类型,类型不匹配触发编译错误 - 额外注意:你现有代码还有两处隐含错误:
Article类的author属性定义为非空String但fromJson方法里会返回null;EnumValues类中用late修饰的reverseMap判空逻辑不符合空安全规则,也需要同步修复
解决方案
方案1:允许枚举字段为空(适配接口字段可能为空的场景)
修改步骤:
- 修改
Source类的属性和构造参数,调整为可空类型 - 修正
EnumValues类的reverseMap定义,适配空安全规则 - 同步修正
Article类的author等可能为空的属性定义
修改后的完整代码片段:
// 修正EnumValues类 class EnumValues<T> { Map<String, T> map; Map<T, String>? reverseMap; // 去掉late,改为可空类型 EnumValues(this.map); Map<T, String> get reverse { reverseMap ??= map.map((k, v) => MapEntry(v, k)); return reverseMap!; } } // 修正Source类 class Source { Source({ this.id, // 去掉required,改为可空 this.name, // 去掉required,改为可空 }); Id? id; // 改为可空类型 Name? name; // 改为可空类型 factory Source.fromJson(Map<String, dynamic> json) => Source( id: idValues.map[json["id"]], name: nameValues.map[json["name"]], ); Map<String, dynamic> toJson() => { "id": idValues.reverse[id], "name": nameValues.reverse[name], }; } // 修正Article类的可空字段 class Article { Article({ required this.source, this.author, // 改为可空 required this.title, required this.description, required this.url, required this.urlToImage, required this.publishedAt, required this.content, }); Source source; String? author; // 改为可空类型 String title; String description; String url; String urlToImage; DateTime publishedAt; String content; // 剩余fromJson、toJson代码无需调整 }
方案2:强制枚举字段非空(兜底默认值避免空值)
如果业务要求枚举字段不能为null,可以先给枚举新增unknown兜底值,解析时如果找不到对应值就返回兜底值:
修改步骤:
- 给
Id、Name枚举新增unknown选项 - 解析时用
??运算符指定默认兜底值 - 同步修正
EnumValues、Article类的空安全问题
修改后的核心代码片段:
// 新增unknown枚举值 enum Id { THE_WALL_STREET_JOURNAL, unknown } final idValues = EnumValues({ "the-wall-street-journal": Id.THE_WALL_STREET_JOURNAL, "unknown": Id.unknown }); enum Name { THE_WALL_STREET_JOURNAL, unknown } final nameValues = EnumValues({ "The Wall Street Journal": Name.THE_WALL_STREET_JOURNAL, "unknown": Name.unknown }); // 修正Source的fromJson方法,指定默认值 factory Source.fromJson(Map<String, dynamic> json) => Source( id: idValues.map[json["id"]] ?? Id.unknown, name: nameValues.map[json["name"]] ?? Name.unknown, );
内容的提问来源于stack exchange,提问作者Shehryar Ashraf
相关产品推荐
相关产品推荐

