Flutter调用HAPIBOOK API时Map转List类型不匹配报错排查
问题原因
核心错误是接口返回结构和解析逻辑不匹配,和你写的authors字段转换逻辑无关:
- 你当前调用的
/book/{书籍ID}接口,返回值是{}包裹的单本图书Map对象,不是[]包裹的图书列表数组,你贴的返回JSON结构也能验证这一点 - 代码里先把响应体解析成了
Map类型,却直接传给了要求入参为List的hapiBookfromsnapshot方法,强行把Map类型传给List类型参数,直接触发你看到的类型匹配异常 - 额外存在潜在风险:模型类中
rating、pages字段定义为int类型,如果接口返回字符串格式的数字,会触发新的类型报错,解析时需要做类型兜底处理
修复方案
根据接口实际返回结构调整解析逻辑,单对象接口走单对象解析方法,列表接口再走列表解析方法,不要混用。
修正API调用逻辑
import 'dart:convert'; import 'package:fluttrapi2/models/hapi_book_model.dart'; import 'package:http/http.dart' as http; class FetchApi { // 当前单本查询接口返回单个图书对象,返回值调整为HapiBook? static Future<HapiBook?> fetchSingleBook() async { var url = Uri.https('hapi-books.p.rapidapi.com', '/book/56597885'); final res = await http.get(url, headers: { 'X-RapidAPI-Key': '替换为你自己的有效RapidAPI密钥', 'X-RapidAPI-Host': 'hapi-books.p.rapidapi.com' }); if (res.statusCode == 200) { Map<String, dynamic> json = jsonDecode(res.body); // 单Map对象直接调用fromJson构造解析,不要传列表解析方法 return HapiBook.fromJson(json); } return null; } // 后续如果调用榜单、搜索类返回图书数组的接口,用这个方法 static Future<List<HapiBook>?> fetchBookList() async { // 替换为实际返回数组结构的接口路径 var url = Uri.https('hapi-books.p.rapidapi.com', '/替换为列表接口路径'); final res = await http.get(url, headers: { 'X-RapidAPI-Key': '替换为你自己的有效RapidAPI密钥', 'X-RapidAPI-Host': 'hapi-books.p.rapidapi.com' }); if (res.statusCode == 200) { // 确认响应最外层是[]数组结构时,再转List传给列表解析方法 List<dynamic> jsonList = jsonDecode(res.body); return HapiBook.hapiBookfromsnapshot(jsonList); } return null; } }
优化模型类增加类型兜底
避免接口返回字段类型和预期不一致时抛出异常:
import 'dart:convert'; HapiBook hapiBookFromJson(String str) => HapiBook.fromJson(json.decode(str)); String hapiBookToJson(HapiBook data) => json.encode(data.toJson()); class HapiBook { HapiBook({ required this.bookId, required this.name, required this.cover, required this.url, required this.authors, required this.rating, required this.pages, required this.publishedDate, required this.synopsis, }); int bookId; String name; String cover; String url; List<String> authors; int rating; int pages; String publishedDate; String synopsis; factory HapiBook.fromJson(Map<String, dynamic> json) => HapiBook( bookId: json["book_id"] is int ? json["book_id"] : int.tryParse(json["book_id"].toString()) ?? 0, name: json["name"]?.toString() ?? '', cover: json["cover"]?.toString() ?? '', url: json["url"]?.toString() ?? '', authors: json["authors"] == null ? [] : List<String>.from(json["authors"].map((x) => x.toString())), rating: json["rating"] is int ? json["rating"] : int.tryParse(json["rating"].toString()) ?? 0, pages: json["pages"] is int ? json["pages"] : int.tryParse(json["pages"].toString()) ?? 0, publishedDate: json["published_date"]?.toString() ?? '', synopsis: json["synopsis"]?.toString() ?? '', ); static List<HapiBook> hapiBookfromsnapshot(List snapshot) { return snapshot.map((data) { return HapiBook.fromJson(data as Map<String, dynamic>); }).toList(); } Map<String, dynamic> toJson() => { "book_id": bookId, "name": name, "cover": cover, "url": url, "authors": List<dynamic>.from(authors.map((x) => x)), "rating": rating, "pages": pages, "published_date": publishedDate, "synopsis": synopsis, }; }
解析接口前先确认响应最外层结构:最外层为
{}对应单对象解析逻辑,最外层为[]对应列表解析逻辑,二者不要混用,就能避免绝大多数这类类型转换错误。
内容的提问来源于stack exchange,提问作者DAni M
相关产品推荐
相关产品推荐

