Flutter API解析报错:List<dynamic>非Map<String,dynamic>子类型
Flutter API解析错误:Type List Is Not A Subtype Of Type Map<String, dynamic> 解决方法
你的错误核心有两点:
- API返回的是外层包含
data字段的JSON对象,不是直接的书籍数组,此前的解析逻辑未处理该外层结构 - API返回字段为
name、icon,但你的Book模型使用title、image,字段不匹配会引发解析异常
1. 修正Book模型类
适配API返回的字段映射(name→title,icon→image),同时添加列表解析方法:
import 'dart:convert'; // 解析书籍列表的方法 List<Book> bookListFromJson(String str) => List<Book>.from(json.decode(str)["data"].map((x) => Book.fromJson(x))); class Book { int? id; String? title; String? description; String? image; String? author; Book({ this.id, this.title, this.description, this.image, this.author, }); // 从JSON解析,注意字段映射 factory Book.fromJson(Map<String, dynamic> json) => Book( id: json["id"], title: json["name"], // API返回的name对应模型的title description: json["description"] ?? "", // 处理可能的null值 image: json["icon"], // API返回的icon对应模型的image author: json["author"] ?? "", ); Map<String, dynamic> toJson() => { "id": id, "title": title, "description": description, "image": image, "author": author, }; }
2. 修正BookController的解析逻辑
先提取外层JSON的data字段,再遍历解析每一项数据:
import 'dart:convert'; import 'package:elibrary/model/books.dart'; import 'package:elibrary/services/repository/book_repository.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; class BookController extends GetxController { BookRepository bookRepository = BookRepository(); RxBool isLoading = false.obs; RxList<Book> bookList = <Book>[].obs; @override void onInit() { super.onInit(); fetchBooksList(); } Future<void> fetchBooksList() async { isLoading(true); try { Response bookResponse = await bookRepository.fetchBooks(); if (bookResponse.statusCode == 200) { // 两种解析方式二选一即可 // 方式一:使用模型中定义的bookListFromJson方法 final List<Book> books = bookListFromJson(bookResponse.bodyString ?? ''); bookList.assignAll(books); // 方式二:手动解析(无需依赖模型的列表方法) // final Map<String, dynamic> responseData = jsonDecode(bookResponse.bodyString ?? ''); // final List<dynamic> booksJson = responseData['data']; // bookList.assignAll(booksJson.map((json) => Book.fromJson(json)).toList()); debugPrint('Total Book List is: ${bookList.length}'); } else { Get.snackbar( '错误', bookResponse.statusText.toString(), snackPosition: SnackPosition.BOTTOM, colorText: Colors.white, backgroundColor: Colors.red, ); } } catch (e) { debugPrint(e.toString()); Get.snackbar( "错误", e.toString(), snackPosition: SnackPosition.BOTTOM, colorText: Colors.white, backgroundColor: Colors.red, duration: const Duration(seconds: 5), ); } finally { isLoading(false); } } }
关键注意事项
- 必须先从API响应中取出
data字段,该字段对应的值才是书籍数组,直接解析整个响应体必然触发类型不匹配错误 - 严格对齐API返回字段与模型字段的映射关系,避免因字段名不一致导致的解析失败或字段为null
- 建议为可选字段设置默认值(如
?? ""),避免运行时null异常
内容的提问来源于stack exchange,提问作者Kennedy Owusu
相关产品推荐
相关产品推荐

