Flutter解析JSON响应访问数组字段时触发Range error问题咨询
问题根因
触发RangeError、兜底逻辑不生效的核心原因如下:
- 数组索引类型错误:访问
addressListings元素时用了字符串'0'/'1'作为索引,Dart中List的索引必须是int类型,传字符串会直接触发类型/范围错误,后续的空判断、兜底逻辑完全不会执行。 - 未校验数组长度:
addressListings长度可能为1,直接访问索引1的位置时,只要数组长度不足就会直接抛出RangeError,你写的?[]空判断仅能判断数组本身是否为null,无法判断目标索引是否存在。 - 字段层级匹配错误:JSON中
fullName、listings是根节点字段,不在items数组的子对象内,原解析逻辑从items子元素中取这两个字段永远拿不到有效值。
另外原代码还存在多处语法/拼写错误:比如as list应为as List、Uri,parse应为Uri.parse、reponse拼写错误、map[imgUrl]的key未加引号、CustomerDetails构造函数的括号位置错误。
修复方案
1. 修正数据模型
addressListings可能包含住宅、商业两类金额,建议拆分两个字段分别存储,从根源避免硬编码索引的问题:
class CustomerDetails { final String fullName; final String listings; final String type; final String imgUrl; final String id; final String residentialAmount; final String commercialAmount; CustomerDetails({ required this.fullName, required this.listings, required this.type, required this.imgUrl, required this.id, required this.residentialAmount, required this.commercialAmount, }); }
2. 修正解析与网络请求逻辑
解析addressListings时先转成List,优先按type遍历匹配对应值,天然兼容数组长度为1/2的场景,不会触发范围错误:
class GetCustomerData{ Future<List<CustomerDetails>> fetchData(queryStr) async { try{ var response = await http.get(Uri.parse(apiUrl+queryStr)); if(response.statusCode == 200){ return _parseResponse(response.body); }else{ print('Request failed with status: ${response.statusCode}'); throw Exception('Request error'); } } on TimeoutException catch (_) { print('Timeout Error'); throw Exception('Timeout'); } } } List<CustomerDetails> _parseResponse(String jsonStr){ final jsonMap = jsonDecode(jsonStr); // 先提取根节点公共字段 final String fullName = jsonMap['fullName'] ?? ''; final String listings = jsonMap['listings'] ?? '0'; final itemsList = jsonMap['items'] as List; return itemsList.map((itemMap){ // 处理addressListings数组 final addressList = itemMap['addressListings'] as List; String resAmount = 'Not Available'; String comAmount = 'Not Available'; // 遍历按type匹配,兼容数组长度1/2的情况 for(var addr in addressList){ if(addr['type'] == 'residential'){ resAmount = addr['amount'] ?? 'Not Available'; } if(addr['type'] == 'commerical'){ // 此处保持和接口返回的拼写一致,不要自行修改为正确拼写commercial comAmount = addr['amount'] ?? 'Not Available'; } } return CustomerDetails( id: itemMap['id'] ?? '', fullName: fullName, listings: listings, type: itemMap['type'] ?? '', imgUrl: itemMap['imgUrl'] ?? '', residentialAmount: resAmount, commercialAmount: comAmount, ); }).toList(); }
如果一定要按索引取值而非按type匹配,取对应索引前必须先判断数组长度:比如取索引1前先判断
addressList.length > 1,长度不足直接返回兜底值即可,不会触发RangeError。
内容的提问来源于stack exchange,提问作者Arun-
相关产品推荐
相关产品推荐

