У меня есть небольшая программа, которая манипулирует некоторыми данными JSON с помощью этой структуры:
{
"categories": [{
"id": 0,
"title": "cat1"
}],
"drinks": [{
"categoryId": 0,
"image": "image",
"title": "title",
"text": "text"
}]
}
Все работает хорошо, если я кодирую с использованием динамических типов или ключевого слова вар, но при объявлении типов я получаю следующую ошибку.
'List<dynamic>' is not a subtype of type 'List<Map<String, dynamic>>'.
Вот эта программа:
import 'dart:convert';
main(List<String> args) {
String source = ''' {
"categories": [{
"id": 0,
"title": "cat1"
}],
"drinks": [{
"categoryId": 0,
"image": "image",
"title": "title",
"text": "text"
}]
}''';
var json = jsonDecode(source);
// Dynamic types, works ok!
var categories = json['categories'];
var title = categories[0]['title'];
var id = categories[0]['id'];
print('$title with $id');
// Explicit types, error!
List<Map<String,dynamic>> categories2 = json['categories'];
String title2 = categories2[0]['title'];
int id2 = categories2[0]['id'];
print('$title2 with $id2');
}
Почему я получаю эту ошибку? categories относится к типу List<dynamic>, но почему это не List<Map<String,dynamic>>?

В Dart тип элемента списка предоставляется при создании списка и сохраняется как часть значения списка. Каждый тип, который вы добавляете в список, проверяется на принадлежность к этому типу. Это отличается от Java, где аргументы универсального типа стираются во время выполнения.
Это означает, что Dart List<dynamic> не совпадает с List<Map<String, dynamic>>, даже если оба списка содержат только экземпляры Map<String, dynamic>>. Например, вы можете добавить целое число к первому, но не ко второму.
Список JSON может содержать любое значение JSON.
В этом случае ваш список содержит только значения, которые являются картами, но это может быть совпадением. Парсер JSON не проверяет сначала исходный код, чтобы увидеть, содержит ли список только один тип объектов, вместо этого он просто создает List<dynamic> и помещает в него элементы. Созданный список является изменяемым, поэтому кто-то может добавить целое число в этот список после того, как он будет возвращен. Этот код сломается, если синтаксический анализатор вместо этого сделает список List<Map<String, dynamic>>.
Итак, ваш список — это List<dynamic>, потому что все списки JSON, созданные jsonParse, это... и было бы критическим изменением сделать их чем-то другим.