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
相关产品推荐
相关产品推荐

