Dart空安全下json_serializable解析JSON模型非空属性报错问题咨询
你遇到的崩溃不是json_serializable的bug,是使用方式错误导致的:
- 你在构造函数体内给
errors、meta设置的初始值完全不生效:json_serializable生成的反序列化代码会在调用构造函数后,通过级联运算符直接覆盖这两个字段的值,你之前写的初始值会被直接替换。 - json_serializable默认不会自动处理构造函数体内的赋值逻辑,它只会识别两类默认值配置:构造函数命名参数的默认值、
@JsonKey注解的defaultValue属性。
解决方法
方法1(最推荐):将可变字段移入构造函数命名参数,配置默认值
这种写法不需要额外加注解,代码更简洁,json_serializable会自动识别构造参数的默认值生成空判断逻辑:
@JsonSerializable(explicitToJson: true) class ResponseStatus extends Equatable { final String errorCode; final String message; final String stackTrace; final List<ResponseError> errors; final Map<String, String> meta; ResponseStatus({ this.errorCode = '', this.message = '', this.stackTrace = '', this.errors = const [], this.meta = const {}, }); factory ResponseStatus.fromJson(Map<String, dynamic> json) => _$ResponseStatusFromJson(json); Map<String, dynamic> toJson() => _$ResponseStatusToJson(this); @override List<Object?> get props => [errorCode, message, stackTrace, errors, meta]; }
方法2:给可能缺失的字段加@JsonKey注解配置默认值
如果你不想改动构造函数的参数结构,可以用这种方式单独配置字段默认值:
@JsonSerializable(explicitToJson: true) class ResponseStatus extends Equatable { final String errorCode; final String message; final String stackTrace; @JsonKey(defaultValue: <ResponseError>[]) final List<ResponseError> errors; @JsonKey(defaultValue: <String, String>{}) final Map<String, String> meta; ResponseStatus({ this.errorCode = '', this.message = '', this.stackTrace = '', }) : errors = [], meta = {}; factory ResponseStatus.fromJson(Map<String, dynamic> json) => _$ResponseStatusFromJson(json); Map<String, dynamic> toJson() => _$ResponseStatusToJson(this); @override List<Object?> get props => [errorCode, message, stackTrace, errors, meta]; }
修改后重新运行build_runner生成代码,你会看到生成的_$ResponseStatusFromJson方法里,对errors和meta的取值会自动加上空判断和默认值 fallback,不会再直接做强转导致空类型异常。
针对你最开始的核心疑问:不需要把所有可能缺失的字段都声明为可空类型。只要提前给字段配置好合理的默认值,既可以满足空安全要求,也不需要在业务层写大量判空逻辑,完全符合Dart空安全的设计目标。
内容的提问来源于stack exchange,提问作者ThommyB
相关产品推荐
相关产品推荐

