Flutter调用猫API遇类型不匹配:期望Map<String,dynamic>却得到List<dynamic>
问题:调用TheCatAPI时出现类型不匹配错误
调用TheCatAPI获取图片时,遇到错误:类型为'Map<String, dynamic>',但实际得到类型为'List
原Flutter代码(状态类)
class _ApiState extends State<Api> { Future<CatData> fetchcat() async { final response = await http.get(Uri.parse('https://api.thecatapi.com/v1/images/search')); if (response.statusCode == 200) { return CatData.fromJson(json.decode(response.body)); //return CatData.fromJson(jsonDecode(response.body) as Map<String, dynamic>); } else { throw Exception('Failed to load album'); } } late Future<CatData> futureAlbum; @override void initState() { super.initState(); futureAlbum = fetchcat(); } @override Widget build(BuildContext context) { return FutureBuilder<CatData>( future: fetchcat(), builder: (context, snapshot) { if (snapshot.hasData) { return Image.network(snapshot.data!.imagen); } else if (snapshot.hasError) { return Text("${snapshot.error}"); } return CircularProgressIndicator(); }, ); } }
原模型类代码
class CatData { String imagen; CatData({required this.imagen}); factory CatData.fromJson(Map<String, dynamic> json) { return CatData( imagen: json['url'], ); } }
问题原因
TheCatAPI的/v1/images/search接口返回的是**数组(List[{"id":"xxx","url":"xxx",...}])。而你的代码直接将整个响应体解析后传给CatData.fromJson,该方法期望接收单个对象(Map<String, dynamic>),因此触发类型不匹配错误。
解决方案
方案1:获取单张图片(适配当前代码逻辑)
修改fetchcat方法,先将响应解析为数组,再取出数组第一个元素传入模型类:
Future<CatData> fetchcat() async { final response = await http.get(Uri.parse('https://api.thecatapi.com/v1/images/search')); if (response.statusCode == 200) { // 解析为数组后取第一个元素 List<dynamic> catList = json.decode(response.body); return CatData.fromJson(catList.first as Map<String, dynamic>); } else { throw Exception('Failed to load cat image'); } }
方案2:获取多张图片(扩展场景)
如果需要加载多张猫咪图片,可修改方法返回数组类型,并调整FutureBuilder逻辑:
- 修改数据获取方法:
Future<List<CatData>> fetchCats() async { // 加limit参数指定返回数量 final response = await http.get(Uri.parse('https://api.thecatapi.com/v1/images/search?limit=5')); if (response.statusCode == 200) { List<dynamic> catList = json.decode(response.body); // 遍历数组生成CatData列表 return catList.map((catJson) => CatData.fromJson(catJson as Map<String, dynamic>)).toList(); } else { throw Exception('Failed to load cat images'); } }
- 调整FutureBuilder:
@override Widget build(BuildContext context) { return FutureBuilder<List<CatData>>( future: fetchCats(), builder: (context, snapshot) { if (snapshot.hasData) { return ListView.builder( itemCount: snapshot.data!.length, itemBuilder: (context, index) { return Image.network(snapshot.data![index].imagen); }, ); } else if (snapshot.hasError) { return Text("${snapshot.error}"); } return CircularProgressIndicator(); }, ); }
通用建议
消费API时,第一步要确认接口返回的数据结构:
- 直接在浏览器打开API地址,查看返回是数组(以
[开头)还是单个对象(以{开头) - 如果是数组,必须先解析为
List<dynamic>,再遍历或取出元素处理;如果是单个对象,直接解析为Map<String, dynamic>
内容的提问来源于stack exchange,提问作者yorman lopez
相关产品推荐
相关产品推荐

