Flutter调用Jikan API遇类型转换错误,请求排查解决
解决Flutter调用Jikan API获取Top动漫时的_CastError问题
错误原因
你遇到的_InternalLinkedHashMap<String, dynamic>' is not a subtype of type 'List?' in type cast错误,本质是Jikan的Top动漫API返回的不是直接的数组,而是一个包含data字段的JSON对象,直接把整个响应转为List会导致类型不匹配。
Jikan v4的Top动漫API响应结构示例:
{ "data": [ {"mal_id": 1, "title": "Fullmetal Alchemist: Brotherhood", ...}, // 更多动漫数据 ], "pagination": {...}, "links": {...}, "meta": {...} }
常见错误代码示例
你大概率写了类似这样的代码,直接将整个响应转为List:
final response = await http.get(Uri.parse('https://api.jikan.moe/v4/top/anime')); if (response.statusCode == 200) { // 这里直接转List会触发类型错误 List<dynamic> topAnime = json.decode(response.body) as List; }
修正后的基础代码
先把响应转为Map,再取出data字段对应的List:
import 'dart:convert'; import 'package:http/http.dart' as http; Future<void> fetchTopAnime() async { final url = Uri.parse('https://api.jikan.moe/v4/top/anime'); final response = await http.get(url); if (response.statusCode == 200) { // 第一步:将响应转为Map类型 final Map<String, dynamic> responseMap = json.decode(response.body) as Map<String, dynamic>; // 第二步:取出data字段对应的List final List<dynamic> animeList = responseMap['data'] as List; // 遍历输出动漫标题示例 for (final anime in animeList) { print('${anime['mal_id']}: ${anime['title']}'); } } else { throw Exception('加载Top动漫失败,状态码:${response.statusCode}'); } }
进阶:类型安全的模型类处理
为避免手动类型转换出错,建议创建Anime模型类配合json_serializable包做序列化:
- 添加依赖到
pubspec.yaml:
dependencies: json_annotation: ^4.8.1 dev_dependencies: build_runner: ^2.4.4 json_serializable: ^6.7.0
- 创建
anime.dart模型文件:
import 'package:json_annotation/json_annotation.dart'; part 'anime.g.dart'; @JsonSerializable() class Anime { final int mal_id; final String title; @JsonKey(name: 'images') final Map<String, dynamic> imageData; Anime({ required this.mal_id, required this.title, required this.imageData, }); // 从JSON转模型 factory Anime.fromJson(Map<String, dynamic> json) => _$AnimeFromJson(json); // 模型转JSON Map<String, dynamic> toJson() => _$AnimeToJson(this); // 快速获取封面图URL String get coverImage => imageData['jpg']['image_url'] as String; }
- 运行命令生成序列化代码:
flutter pub run build_runner build
- 使用模型类的请求代码:
if (response.statusCode == 200) { final Map<String, dynamic> responseMap = json.decode(response.body) as Map<String, dynamic>; // 将data列表转为Anime模型列表 final List<Anime> topAnime = (responseMap['data'] as List) .map((animeJson) => Anime.fromJson(animeJson)) .toList(); // 处理模型数据示例 for (final anime in topAnime) { print('${anime.mal_id}: ${anime.title}'); print('封面图:${anime.coverImage}'); } }
注意事项
- 确认API版本:Jikan v4的响应结构包裹在
data字段中,若使用v3版本结构会不同,建议优先使用v4 API。 - 空值防护:实际开发中建议给
responseMap['data']添加空值判断,避免空指针异常:
final List<dynamic>? animeList = responseMap['data'] as List?; if (animeList != null) { // 处理列表逻辑 } else { throw Exception('API响应中未找到data字段'); }
内容的提问来源于stack exchange,提问作者Emre Isikgor
相关产品推荐
相关产品推荐

