Flutter解析复杂多层JSON响应并转Dart模型显示问题
解决Flutter嵌套数组解析与ListView.builder失效问题
一、确认Dart模型类的正确性
在线JSON转Dart工具生成的代码可能存在嵌套数组解析错误,你需要确保每个嵌套层级的fromJson方法正确处理List类型。以下是适配你数据结构的示例模型:
class ActivityResponse { final List<ActivityFieldValue> activityFieldValueList; ActivityResponse({required this.activityFieldValueList}); factory ActivityResponse.fromJson(Map<String, dynamic> json) { return ActivityResponse( activityFieldValueList: List<ActivityFieldValue>.from( json['activityFieldValueList'].map((x) => ActivityFieldValue.fromJson(x)), ), ); } } class ActivityFieldValue { final AttributeType attributeType; ActivityFieldValue({required this.attributeType}); factory ActivityFieldValue.fromJson(Map<String, dynamic> json) { return ActivityFieldValue( attributeType: AttributeType.fromJson(json['attributeType']), ); } } class AttributeType { final List<LookupValues> lookupValues; AttributeType({required this.lookupValues}); factory AttributeType.fromJson(Map<String, dynamic> json) { return AttributeType( lookupValues: List<LookupValues>.from( json['lookupValues'].map((x) => LookupValues.fromJson(x)), ), ); } } class LookupValues { final String lookupValue; LookupValues({required this.lookupValue}); factory LookupValues.fromJson(Map<String, dynamic> json) { return LookupValues( lookupValue: json['lookupValue'] ?? '', // 增加空值处理避免崩溃 ); } }
二、API响应解析
使用http包发起请求并解析数据,确保异常处理逻辑完善:
import 'dart:convert'; import 'package:http/http.dart' as http; Future<ActivityResponse> fetchActivityData() async { final response = await http.get(Uri.parse('你的API接口地址')); if (response.statusCode == 200) { return ActivityResponse.fromJson(jsonDecode(response.body)); } else { throw Exception('请求失败,状态码:${response.statusCode}'); } }
三、修复ListView.builder不工作问题
常见失效原因是列表长度不匹配或未正确遍历嵌套层级,提供两种展示方案:
方案1:扁平化展示所有lookupValue
将嵌套数组中的所有lookupValue收集到一个列表,直接展示:
class ActivityScreen extends StatefulWidget { @override _ActivityScreenState createState() => _ActivityScreenState(); } class _ActivityScreenState extends State<ActivityScreen> { late Future<ActivityResponse> _futureData; @override void initState() { super.initState(); _futureData = fetchActivityData(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('嵌套数据展示')), body: FutureBuilder<ActivityResponse>( future: _futureData, builder: (context, snapshot) { if (snapshot.hasData) { // 收集所有lookupValue final allLookupValues = <String>[]; for (final field in snapshot.data!.activityFieldValueList) { for (final lookup in field.attributeType.lookupValues) { allLookupValues.add(lookup.lookupValue); } } return ListView.builder( itemCount: allLookupValues.length, // 匹配列表长度 itemBuilder: (context, index) { return ListTile( title: Text(allLookupValues[index]), ); }, ); } else if (snapshot.hasError) { return Center(child: Text('错误:${snapshot.error}')); } // 加载中状态 return const Center(child: CircularProgressIndicator()); }, ), ); } }
方案2:嵌套展开展示
保留层级结构,用ExpansionTile展示每个字段下的所有lookupValue:
// 替换FutureBuilder中的返回部分 if (snapshot.hasData) { return ListView.builder( itemCount: snapshot.data!.activityFieldValueList.length, itemBuilder: (context, index) { final field = snapshot.data!.activityFieldValueList[index]; return ExpansionTile( title: Text('字段 ${index + 1}'), children: field.attributeType.lookupValues.map((lookup) { return ListTile(title: Text(lookup.lookupValue)); }).toList(), ); }, ); }
常见排查点
- 检查模型类中
lookupValues是否被定义为List<LookupValues>,而非单个对象 - 确认
ListView.builder的itemCount与数据源长度完全匹配 - 给
lookupValue增加空值处理,避免API返回null导致崩溃
内容的提问来源于stack exchange,提问作者mbStack
相关产品推荐
相关产品推荐

