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

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-

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.06 16:15:42