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

Flutter News Toolkit获取分类时类型转换错误求助

解决type 'List<dynamic>' is not a subtype of type 'Map<String, dynamic>'类型转换错误

问题根源

你的分类接口(WordPress的/wp-json/wp/v2/categories)返回的JSON是数组(List),但你在两处代码中都强行将其转换为Map<String, dynamic>,这直接触发了类型不匹配错误。


分步修复方案

1. 重构HTTP响应扩展方法,适配多格式返回

原扩展方法固定返回Map,无法兼容返回数组的接口。修改为返回dynamic,让每个接口方法自行处理对应格式:

extension on http.Response {
  dynamic json() {
    try {
      final decodedBody = utf8.decode(bodyBytes);
      log("MyLog $decodedBody");
      return jsonDecode(decodedBody);
    } catch (error, stackTrace) {
      Error.throwWithStackTrace(
        BernardinaiApiMalformedResponse(error: error),
        stackTrace,
      );
    }
  }
}

2. 调整CategoriesResponse的JSON解析逻辑

让CategoriesResponse同时支持从数组或对象解析,兼容接口返回格式:

class CategoriesResponse {
  final List<CategoriesInfo> categories;

  CategoriesResponse({required this.categories});

  factory CategoriesResponse.fromJson(dynamic json) {
    // 处理接口直接返回数组的情况(如WordPress分类接口)
    if (json is List) {
      return CategoriesResponse(
        categories: json
            .map((item) => CategoriesInfo.fromJson(item as Map<String, dynamic>))
            .toList(),
      );
    }
    // 处理包含categories字段的对象格式(兼容其他接口)
    else if (json is Map<String, dynamic>) {
      return CategoriesResponse(
        categories: (json['categories'] as List)
            .map((item) => CategoriesInfo.fromJson(item as Map<String, dynamic>))
            .toList(),
      );
    } else {
      throw ArgumentError('Invalid JSON format for CategoriesResponse');
    }
  }
}

3. 修复NewsDataSource中的getCategories方法

WordPress分类接口返回的是分类对象数组,不是包含categories字段的对象,且每个分类是Map结构而非字符串,需修正解析逻辑:

Future<List<Category>> getCategories() async {
  final uri = Uri.parse('https://www.mynewsurl.com/wp-json/wp/v2/categories');
  final categoriesResponse = await http.get(uri);

  if (categoriesResponse.statusCode == HttpStatus.ok) {
    // 直接解析为List<dynamic>
    final List<dynamic> categoriesList = jsonDecode(categoriesResponse.body) as List<dynamic>;
    log("MyLog categoriesList: $categoriesList");
    
    // 从分类对象中提取slug字段,转换为Category枚举
    final List<Category> categories = categoriesList.map((dynamic categoryData) {
      final String categorySlug = (categoryData as Map<String, dynamic>)['slug'] as String;
      log("MyLog categorySlug: $categorySlug");

      return Category.fromString(categorySlug);
    }).toList();
    
    log("MyLog categories to return: $categories");
    return categories;
  } else {
    // 错误处理兼容多种返回格式
    final dynamic errorBody = jsonDecode(categoriesResponse.body);
    throw BernardinaiApiRequestFailure(
      statusCode: categoriesResponse.statusCode,
      body: errorBody is Map<String, dynamic> ? errorBody : {},
    );
  }
}

关键说明

  • 不要强行统一所有接口的返回格式:不同接口可能返回数组或对象,扩展方法需保持灵活性
  • 必须匹配接口实际返回结构:WordPress分类接口直接返回分类对象数组,无需读取categories字段
  • 枚举转换需基于接口返回的实际字段:分类对象包含slug/name等字段,无法直接转换为字符串

内容的提问来源于stack exchange,提问作者T1D

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 09:37:02