You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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逻辑:

  1. 修改数据获取方法:
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');
  }
}
  1. 调整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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 22:09:34