dart - Dart null 安全性和使用 json_serializable 将 JSON 解析为模型
问题描述
在使用各种工具将 JSON 反序列化为 Dart 并且对null 安全性感到非常沮丧之后,我有一个非常普遍的问题。json_serializable
生成.fromJson
和消息的包.toJson
应该关心 NULL 值。但我根本无法做到这一点!所以一百万美元的问题是:
我是否必须将模型的所有属性声明为 NULLABLE(带有 ? 例如String? myString
),如果在返回的 JSON 中有可能该属性可能丢失或为 NULL ?
当我不将此类成员声明为 NULLABLE 时,我总是会收到此错误:
Unhandled Exception: type 'Null' is not a subtype of type 'List<dynamic>' in type cast
这些错误总是发生在生成的FromJson
方法中。这是导致问题的示例 JSON:
"responseStatus": {
"errorCode": "500",
"message": "This is a test message",
"errors": [
{
"errorCode": "300",
"fieldName": "a field name",
"message": "a message",
"meta": {
"a key": "a value"
}
}
],
"meta": {
"some field": "some value"
}
}
该errors
数组包含一个数组,该数组本身可能包含也可能不包含( )error objects
的数组。如果没有错误,则不提交数组,如下所示:key value pairs
meta
errors
"responseStatus": {
"errorCode": "500",
"message": "This is a test message",
"meta": {
"some field": "some value"
}
在这种情况下,生成的 DART 代码会崩溃,如下所示:
ResponseStatus _$ResponseStatusFromJson(Map<String, dynamic> json) =>
ResponseStatus(
errorCode: json['errorCode'] as String? ?? '',
message: json['message'] as String? ?? '',
stackTrace: json['stackTrace'] as String? ?? '',
)
..errors = (json['errors'] as List<dynamic>) // <<==== This is crashing if errors is not in the returned JSON
.map((e) => ResponseError.fromJson(e as Map<String, dynamic>))
.toList()
..meta = Map<String, String>.from(json['meta'] as Map);
我创建的模型类如下所示:
@JsonSerializable(explicitToJson: true)
class ResponseStatus extends Equatable {
late final String errorCode;
late final String message;
late final String stackTrace;
late final List<ResponseError> errors;
late final Map<String, String> meta;
ResponseStatus({this.errorCode = '', this.message = '', this.stackTrace = ''}) {
this.errors = [];
this.meta = Map();
}
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];
}
我创建了一个默认构造函数,它用一个值初始化所有成员(不可为空)。
如果我必须声明所有模型成员,因为nullable
这将无法使用,因为在我的颤振小部件中,我必须编写数千个if statements
来检查成员是否为空。我认为避免这种情况是 sound null safety 背后的想法之一。
我很想知道这是否是一个错误或者我是如何让这个东西工作的!
解决方案
这是预期的行为。如果未给出数据,则必须发生崩溃,因为不可为空的变量永远不会有null
值。
但是,您可以使用自定义反序列化函数来处理这种情况:
@JsonKey(fromJson: optionalErrorListFromJson)
late final List<ResponseError> errors;
List<ResponseError> optionalErrorListFromJson(List<dynamic>? errors) {
if (errors == null) return const [];
return errors
.map((e) => ResponseError.fromJson(e as Map<String, dynamic>))
.toList(growable: false)
}
推荐阅读
- typescript - 使用泛型类型接口泛型类型类
- m2doc - 访问属性模板构造参数的描述属性
- php - 控制器或 FormBuilder 中的 Symfony 3 最大文件大小上传约束
- python - Python Pygame 直接在 Class 中使用 command 或调用 def 会导致不同的效果,为什么?
- powerbi - 如何从列中提取每个不同的名称并使用 Power BI 将其转换为分类变量
- java - RxJava retryWhen 重试返回可完成的整个方法
- visual-studio - TSVN - 当前解决方案的未决更改,而不是所有结帐文件夹
- php - PHP exec(node) 只为 -v 运行,但不为 .js 文件运行
- azure - 如何在 Azure 中设置全局 vnet 对等互连
- java - Java - 如何使用字符串数组从列表中取出项目