Flutter解析嵌套JSON时venue/branch详情为空问题求助
Flutter API解析venue/branch详情为null的排查与解决方案
问题描述
Flutter应用调用API获取订单数据时,venue_detail、branch_detail及其嵌套字段返回null,但Postman中能看到完整的非空响应,API本身正常,问题出在数据解析环节。
排查步骤
核对请求一致性
- 对比Flutter代码与Postman的请求参数:确认
BASE_URL、Authorization令牌、user_id参数完全一致 - 检查请求头:确保
Content-type、Accept头与Postman配置相同
- 对比Flutter代码与Postman的请求参数:确认
查看原始解析数据
- 运行代码后查看控制台的
getting pending orders $extractedData输出,确认返回的数组中每个订单对象是否包含venue_detail和branch_detail字段 - 在
extractedData.forEach循环内添加print('单个订单数据: $prodData');,直接打印单条订单的完整结构,定位字段是否存在
- 运行代码后查看控制台的
检查类型转换与空安全
- 当前代码中
json.decode(response.body)['success'] as List<dynamic>属于强制类型转换,若API返回结构异常会导致解析失败,需添加类型校验
- 当前代码中
修复方案
1. 优化请求与解析的类型安全
修改解析逻辑,增加类型检查与空安全处理:
Future<bool> getPresentOrders({ required token, required userId, }) async { try { final response = await http.post( Uri.parse(BASE_URL + '/api/get_present_orders'), headers: { "Content-type": "application/json", "Accept": "application/json", 'Authorization': 'Bearer $token', }, body: jsonEncode({ 'user_id': userId, }), ); final responseData = json.decode(response.body); // 先校验顶层结构 if (responseData is! Map<String, dynamic> || !responseData.containsKey('success')) { return false; } final extractedData = responseData['success']; // 校验success字段是否为列表 if (extractedData is! List) { return false; } print('获取的订单列表数据: $extractedData'); if (response.statusCode == 200) { final List<Order> loadedOrderList = []; for (final prodData in extractedData) { // 确保prodData是Map类型 if (prodData is! Map<String, dynamic>) continue; // 提取嵌套对象并做空安全处理 final venueDetail = prodData['venue_detail'] as Map<String, dynamic>?; final branchDetail = prodData['branch_detail'] as Map<String, dynamic>?; loadedOrderList.add( Order( venueId: prodData['venue_id'].toString(), branchId: prodData['branch_id'].toString(), orderNumber: prodData['order_unique_id'], orderTime: prodData['order_time'], total: double.parse(prodData['total_price'] ?? '0.00'), orderType: prodData['order_type'], currentStatus: prodData['current_status'], venueName: venueDetail?['venue_name'] ?? '未知商家', venueType: venueDetail?['venue_type'] ?? '未知类型', branchName: branchDetail?['name'] ?? '未知门店', venueLogo: venueDetail?['logo_url'] ?? '', orderItems: () { try { final itemsJson = json.decode(prodData['items_detail'] ?? '[]') as List; return itemsJson.map((item) { final itemMap = item as Map<String, dynamic>; return CartItem( id: itemMap['id'].toString(), title: itemMap['title'].toString(), quantity: int.parse(itemMap['quantity'].toString()), price: double.parse(itemMap['price'].toString()), specialInstruction: itemMap['instructions'].toString(), ); }).toList(); } catch (e) { print('解析订单商品失败: $e'); return []; } }(), ), ); } _or = loadedOrderList.reversed.toList(); } else { print('请求失败: ${response.statusCode}'); } notifyListeners(); return true; } catch (error) { print('解析异常: $error'); rethrow; } }
2. 关键优化点
- 增加类型校验:确保每个层级的JSON结构符合预期,避免强制类型转换导致的隐性错误
- 使用空安全操作符
?.:访问嵌套字段时自动处理null情况,避免直接访问null对象的属性 - 添加异常捕获:对商品列表解析单独捕获异常,避免单个订单解析失败导致整个列表加载失败
- 处理字符串转数值:
total_price是字符串类型,需显式转为double,同时添加默认值
3. 额外排查点
- 若控制台打印的
extractedData中确实没有venue_detail和branch_detail,说明Flutter发送的请求与Postman不一致,需再次核对请求头、令牌、参数 - 检查API是否存在权限差异:部分API可能根据令牌返回不同字段,确保Flutter使用的令牌与Postman相同
内容的提问来源于stack exchange,提问作者Zulqarnain Haider
相关产品推荐
相关产品推荐

