Flutter报错修复:期望Map<String,dynamic>却得到List<dynamic>
解决Flutter API解析分类列表的类型不匹配问题
问题根源
API返回的JSON是数组(ListCategory.fromJson(仅接受单个Map<String, dynamic>)解析整个数组,导致类型不匹配报错:Expected a value of type 'Map<String, dynamic>', but got one of type 'List<dynamic>'。
修复步骤
1. 扩展Category模型,支持列表解析
在Category类中添加静态方法,用于将JSON数组转换为Category对象列表:
import 'dart:convert'; class Category { String? id; String? tenantId; String? userId; String? name; String? description; String? createdAt; String? updatedAt; Category( {this.id, this.tenantId, this.userId, this.name, this.description, this.createdAt, this.updatedAt}); Category.fromJson(Map<String, dynamic> json) { id = json['id']; tenantId = json['tenant_id']; userId = json['user_id']; name = json['name']; description = json['description']; createdAt = json['created_at']; updatedAt = json['updated_at']; } // 新增:将JSON数组转为Category列表 static List<Category> fromJsonList(List<dynamic> jsonList) { return jsonList.map((json) => Category.fromJson(json)).toList(); } Map<String, dynamic> toJson() { final Map<String, dynamic> data = new Map<String, dynamic>(); data['id'] = id; data['tenant_id'] = tenantId; data['user_id'] = userId; data['name'] = name; data['description'] = description; data['created_at'] = createdAt; data['updated_at'] = updatedAt; return data; } }
2. 修改API调用函数,返回正确的列表类型
更新getMceaCategories,明确返回类型为Future<List<Category>>,并使用新增的fromJsonList解析数组:
import 'package:http/http.dart' as http; import 'dart:convert'; import 'package:mcea_master_application/config/config.dart'; import 'package:mcea_master_application/models/CategoryModel.dart'; final String urlCategories = '${Config.baseUrl}categories'; // 明确返回类型为Future<List<Category>> Future<List<Category>> getMceaCategories() async { final response = await http.get(Uri.parse(urlCategories), headers: { 'Content-Type': 'application/json', 'Accept': 'application/json', 'Authorization': 'Bearer 6|b8Wi0V95n3fgZyCg3DiJFymdx10jZsX2K58vpVcq', }); if (response.statusCode == 200) { // 解析为List后,用fromJsonList转成Category列表 List<dynamic> jsonList = jsonDecode(response.body); return Category.fromJsonList(jsonList); } else { throw Exception('Falha ao carregar as categorias!'); } }
3. 调整页面代码,使用模型对象访问属性
因为Future返回的是List<Category>,所以在FutureBuilder中直接通过模型属性访问,而非Map索引:
import 'package:flutter/material.dart'; import 'package:carousel_slider/carousel_slider.dart'; import 'package:mcea_master_application/config/config.dart'; import 'package:mcea_master_application/config/mcea-api.dart'; import 'package:mcea_master_application/models/CategoryModel.dart'; class Home extends StatefulWidget { const Home({super.key}); @override State<Home> createState() => _HomeState(); } class _HomeState extends State<Home> { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( backgroundColor: Colors.black, title: Text(Config.title), ), body: FutureBuilder<List<Category>>( future: getMceaCategories(), builder: (context, snapshot) { if (snapshot.hasData) { final categories = snapshot.data!; return ListView.builder( itemCount: categories.length, itemBuilder: (context, index) { final category = categories[index]; return ListTile( title: Text(category.name ?? 'Sem nome'), ); }); } if (snapshot.hasError) { print(snapshot.error); return Center(child: Text('Erro ao carregar categorias')); } return const Center( child: CircularProgressIndicator(), ); }), ); } }
关键说明
- 移除原页面中无用的
dart:html和dart:js导入,避免不必要的依赖 - 使用
category.name ?? 'Sem nome'处理可能为null的属性,防止空指针异常 - 明确FutureBuilder的泛型类型
List<Category>,提升代码可读性和类型安全性
内容的提问来源于stack exchange,提问作者Anderson Costa
相关产品推荐
相关产品推荐

