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

Flutter解析嵌套JSON报错:List<dynamic>无法转为String的解决方法

解决Flutter解析JSON时“List is not a subtype of String”异常(Bloc+ListView场景)

问题根源

这个异常的核心是JSON响应里的某个字段是数组类型,但quicktype生成的实体类将其错误定义为String类型,解析时强行类型转换导致失败。


解决步骤

1. 核对JSON结构与实体类字段类型

先把后端返回的JSON结构和quicktype生成的CompanyListResponseModel、NameOfDatum类逐字段对比,找出类型不匹配的字段。
举个例子:
假设后端返回的JSON片段是:

{
  "data": [
    {
      "company_name": "XX科技",
      "business_scopes": ["软件开发", "云计算"]
    }
  ]
}

如果quicktype生成的NameOfDatum里把business_scopes定义成了String,那必然会触发异常。

2. 修正实体类的字段类型与解析逻辑

把错误的String类型改成对应的List类型,并修正fromJson方法的解析逻辑:
错误代码(quicktype生成的):

class NameOfDatum {
  String businessScopes;

  NameOfDatum({required this.businessScopes});

  factory NameOfDatum.fromJson(Map<String, dynamic> json) => NameOfDatum(
        businessScopes: json["business_scopes"] as String, // 这里强转String,实际是List
      );
}

修正后代码:

class NameOfDatum {
  List<String> businessScopes;

  NameOfDatum({required this.businessScopes});

  factory NameOfDatum.fromJson(Map<String, dynamic> json) => NameOfDatum(
        businessScopes: List<String>.from(json["business_scopes"].map((item) => item as String)),
      );
}

如果后端可能返回null或空数组,要做空安全处理:

List<String>? businessScopes;

// fromJson里的处理
businessScopes: json["business_scopes"] != null 
    ? List<String>.from(json["business_scopes"].map((item) => item as String))
    : [],

3. 确保Bloc中的解析逻辑正确

在Bloc的事件处理方法中,保证API返回的JSON被正确解析为实体类:

on<FetchCompaniesEvent>((event, emit) async {
  try {
    final response = await _apiService.fetchCompanyList();
    final decodedJson = jsonDecode(response.body);
    final companyList = CompanyListResponseModel.fromJson(decodedJson);
    emit(CompaniesLoadedState(companies: companyList.data));
  } catch (e) {
    emit(CompaniesErrorState(message: e.toString()));
  }
});

注意:不要跳过jsonDecode直接传response.body给fromJson,也不要在解析时做不必要的类型强转。

4. ListView展示适配

在UI层从Bloc状态获取数据后,正确遍历List并展示:

BlocBuilder<CompaniesBloc, CompaniesState>(
  builder: (context, state) {
    if (state is CompaniesLoadedState) {
      return ListView.builder(
        itemCount: state.companies.length,
        itemBuilder: (context, index) {
          final company = state.companies[index];
          return ListTile(
            title: Text(company.companyName),
            subtitle: Text(company.businessScopes.join(" | ")), // 将List转为字符串展示
          );
        },
      );
    } else if (state is CompaniesErrorState) {
      return Center(child: Text(state.message));
    }
    return const Center(child: CircularProgressIndicator());
  },
);

特殊场景处理

如果后端返回的字段类型不规范(比如同一个字段有时是数组有时是字符串),可以在fromJson里做兼容:

businessScopes: json["business_scopes"] is List
    ? List<String>.from(json["business_scopes"].map((item) => item as String))
    : [json["business_scopes"] as String],

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 02:05:34