为什么 json 对象的一种方式有效而另一种方式抛出 null 错误? Dart/Flutter null 安全问题
Why is one way of json to object working and the other throwing null error? Dart/Flutter null safety trouble
我正在学习如何使用 json,不习惯 Dart 的空安全性,目前为止我不喜欢它。但我别无选择,只能适应它。我正在尝试将我的 json 对象列表解析为对象列表。我能够在我的 main 中计算出基础知识,但是当我尝试使用相同的结构在 class 中创建一个实际方法时,我得到了一个空错误。据我所知,我在两者中都做了完全相同的事情,只是添加了用于迭代整个 json 列表的循环。
注意:我当然尝试插入可选的 ?它在哪里询问,但 IDE 不允许这样做。
谁能帮我解释一下我做错了什么?
class 方法错误 jsonToDatabaseSyncItem()
lib/services/remote_database_services.dart:52:43: Error: Property 'length' cannot be accessed on 'List<dynamic>?' because it is potentially null.
- 'List' is from 'dart:core'.
Try accessing using ?. instead.
final jsonListLength = jsonObjectList.length;
^^^^^^
lib/services/remote_database_services.dart:55:38: Error: Operator '[]' cannot be called on 'List<dynamic>?' because it is potentially null.
- 'List' is from 'dart:core'.
var jsonObject = jsonObjectList[index]['DatabaseSyncItem'];
Class 方法(class- RemoteDatabaseService)
// This method will get server database
Future<List<dynamic>?> getRemoteDatabase() async {
final events = QueryBuilder<ParseObject>(ParseObject('Event'));
final apiResponse = await events.query();
if (apiResponse.success && apiResponse.result != null) {
return apiResponse.results;
} else {
return [];
}
}
// Method to parse json result list back to objects
Future<List<dynamic>?> jsonToDatabaseSyncItem() async {
final remoteDatabaseList = await getRemoteDatabase();
final jsonObjectList = await Future.value(remoteDatabaseList); /// This method throws the above
final jsonListLength = jsonObjectList.length; /// error when run in main
for (var index = 0; index == jsonListLength; index++) {
var jsonObject = jsonObjectList[index]['DatabaseSyncItem'];
print(jsonObject);
}
}
主文件工作代码
Future<void> main(List<String> arguments) async {
final test = remoteDatabaseServices.getRemoteDatabase();
Future<List<dynamic>?> getList() {
return Future.value(test);
}
var list = await getList();
print(list?.length);
var jsonObject = list![0]['DatabaseSyncItem'];
print(jsonObject);
var toObject = DatabaseSyncItem.fromJson(jsonObject);
print(toObject);
}
你的 null-safety 问题似乎是缺乏对该功能的理解。我会建议您阅读此处的文档并阅读所有章节:https://dart.dev/null-safety
关于您的代码,您应该考虑什么时候可以 null
以及什么时候可以检查 null
并处理这种情况。在您的示例中,如果发生错误或没有结果 return,似乎 getRemoteDatabase()
应该只是 return 一个空的 List
。所以我们不需要把这个方法的 return 类型设置为 Future<List<dynamic>?>
如果我们稍微重写这个方法:
Future<List<dynamic>> getRemoteDatabase() async {
final events = QueryBuilder<ParseObject>(ParseObject('Event'));
final apiResponse = await events.query();
if (apiResponse.success) {
return apiResponse.results ?? <dynamic>[];
} else {
return <dynamic>[];
}
}
(??
运算符将在这里测试 apiResponse.results
是否为 null,如果是,我们 return <dynamic>[]
。如果不是,我们使用值apiResponse.results
).
由于此方法现在保证永远不会 return null,我们可以使用它来简化下一个方法。我还重写了它以使用 for-each 循环,因为我们真的不需要每个元素的 index
。
Future<void> jsonToDatabaseSyncItem() async {
final jsonObjectList = await getRemoteDatabase();
for (final jsonObject in jsonObjectList) {
print(jsonObject['DatabaseSyncItem']);
}
}
我也删除了这一行,因为它什么都不做。如果 remoteDatabaseList
是一个 Future
你应该只是 await
而不是创建一个新的 Future
.
final jsonObjectList = await Future.value(remoteDatabaseList);
此外,jsonToDatabaseSyncItem()
的 return 类型已更改为 Future<void>
,因为我们从不 returning 任何值。
我对你的 main
有点困惑,但我认为这是最明显的地方,你对 Future
和 null-safety 感到困惑。我试图重写它,使它更干净,但仍然应该这样做:
Future<void> main(List<String> arguments) async {
final list = await getRemoteDatabase();
print(list.length);
final dynamic jsonObject = list[0]['DatabaseSyncItem'];
print(jsonObject);
final toObject = DatabaseSyncItem.fromJson(jsonObject);
print(toObject);
}
我正在学习如何使用 json,不习惯 Dart 的空安全性,目前为止我不喜欢它。但我别无选择,只能适应它。我正在尝试将我的 json 对象列表解析为对象列表。我能够在我的 main 中计算出基础知识,但是当我尝试使用相同的结构在 class 中创建一个实际方法时,我得到了一个空错误。据我所知,我在两者中都做了完全相同的事情,只是添加了用于迭代整个 json 列表的循环。
注意:我当然尝试插入可选的 ?它在哪里询问,但 IDE 不允许这样做。
谁能帮我解释一下我做错了什么?
class 方法错误 jsonToDatabaseSyncItem()
lib/services/remote_database_services.dart:52:43: Error: Property 'length' cannot be accessed on 'List<dynamic>?' because it is potentially null.
- 'List' is from 'dart:core'.
Try accessing using ?. instead.
final jsonListLength = jsonObjectList.length;
^^^^^^
lib/services/remote_database_services.dart:55:38: Error: Operator '[]' cannot be called on 'List<dynamic>?' because it is potentially null.
- 'List' is from 'dart:core'.
var jsonObject = jsonObjectList[index]['DatabaseSyncItem'];
Class 方法(class- RemoteDatabaseService)
// This method will get server database
Future<List<dynamic>?> getRemoteDatabase() async {
final events = QueryBuilder<ParseObject>(ParseObject('Event'));
final apiResponse = await events.query();
if (apiResponse.success && apiResponse.result != null) {
return apiResponse.results;
} else {
return [];
}
}
// Method to parse json result list back to objects
Future<List<dynamic>?> jsonToDatabaseSyncItem() async {
final remoteDatabaseList = await getRemoteDatabase();
final jsonObjectList = await Future.value(remoteDatabaseList); /// This method throws the above
final jsonListLength = jsonObjectList.length; /// error when run in main
for (var index = 0; index == jsonListLength; index++) {
var jsonObject = jsonObjectList[index]['DatabaseSyncItem'];
print(jsonObject);
}
}
主文件工作代码
Future<void> main(List<String> arguments) async {
final test = remoteDatabaseServices.getRemoteDatabase();
Future<List<dynamic>?> getList() {
return Future.value(test);
}
var list = await getList();
print(list?.length);
var jsonObject = list![0]['DatabaseSyncItem'];
print(jsonObject);
var toObject = DatabaseSyncItem.fromJson(jsonObject);
print(toObject);
}
你的 null-safety 问题似乎是缺乏对该功能的理解。我会建议您阅读此处的文档并阅读所有章节:https://dart.dev/null-safety
关于您的代码,您应该考虑什么时候可以 null
以及什么时候可以检查 null
并处理这种情况。在您的示例中,如果发生错误或没有结果 return,似乎 getRemoteDatabase()
应该只是 return 一个空的 List
。所以我们不需要把这个方法的 return 类型设置为 Future<List<dynamic>?>
如果我们稍微重写这个方法:
Future<List<dynamic>> getRemoteDatabase() async {
final events = QueryBuilder<ParseObject>(ParseObject('Event'));
final apiResponse = await events.query();
if (apiResponse.success) {
return apiResponse.results ?? <dynamic>[];
} else {
return <dynamic>[];
}
}
(??
运算符将在这里测试 apiResponse.results
是否为 null,如果是,我们 return <dynamic>[]
。如果不是,我们使用值apiResponse.results
).
由于此方法现在保证永远不会 return null,我们可以使用它来简化下一个方法。我还重写了它以使用 for-each 循环,因为我们真的不需要每个元素的 index
。
Future<void> jsonToDatabaseSyncItem() async {
final jsonObjectList = await getRemoteDatabase();
for (final jsonObject in jsonObjectList) {
print(jsonObject['DatabaseSyncItem']);
}
}
我也删除了这一行,因为它什么都不做。如果 remoteDatabaseList
是一个 Future
你应该只是 await
而不是创建一个新的 Future
.
final jsonObjectList = await Future.value(remoteDatabaseList);
此外,jsonToDatabaseSyncItem()
的 return 类型已更改为 Future<void>
,因为我们从不 returning 任何值。
我对你的 main
有点困惑,但我认为这是最明显的地方,你对 Future
和 null-safety 感到困惑。我试图重写它,使它更干净,但仍然应该这样做:
Future<void> main(List<String> arguments) async {
final list = await getRemoteDatabase();
print(list.length);
final dynamic jsonObject = list[0]['DatabaseSyncItem'];
print(jsonObject);
final toObject = DatabaseSyncItem.fromJson(jsonObject);
print(toObject);
}