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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 07:20:32