如何在Dart中访问复杂JSON对象内的数据?Flutter WebSocket场景
处理Flutter中WebSocket动态JSON数据的实用方案
嘿,这种动态结构的JSON在WebSocket通信里真的太常见了,尤其是不同操作返回的action和datas结构完全不一样的情况。我给你分享几个实际项目里常用的处理思路,保证清晰又好维护:
1. 先解析固定顶层字段,再分支处理
不管action是什么,顶层的action、cbackid、deviceID这些字段应该是固定存在的吧?第一步先把这些固定字段解析出来,再根据action的值去处理对应的datas结构。
示例代码:
import 'dart:convert'; // 假设从WebSocket收到的消息是String类型 void handleWebSocketMessage(String message) { try { // 把JSON字符串转成Map final jsonData = jsonDecode(message) as Map<String, dynamic>; // 提取固定的顶层字段(注意处理可能的空值,避免崩溃) final action = jsonData['action'] as String?; final cbackId = jsonData['cbackid'] as num?; final deviceId = jsonData['deviceID'] as String?; final datas = jsonData['datas'] as Map<String, dynamic>?; // 先做基础校验,缺失关键字段直接返回 if (action == null || datas == null) { print('无效的WebSocket消息:缺少action或datas字段'); return; } // 根据action分支处理不同的datas结构 switch (action) { case 'getProduct': _handleGetProduct(datas); break; case 'updateProduct': _handleUpdateProduct(datas); break; case 'deleteProduct': _handleDeleteProduct(datas); break; default: print('未知的action类型:$action'); } } catch (e) { print('解析JSON失败:$e'); } }
2. 为每个action写单独的处理函数
把不同action的解析逻辑拆成单独的函数,代码会更整洁,也方便后续维护。比如针对getProduct的处理:
void _handleGetProduct(Map<String, dynamic> datas) { final result = datas['result'] as String?; if (result != 'success') { print('获取产品失败:$result'); return; } // 解析product字段 final productMap = datas['product'] as Map<String, dynamic>?; if (productMap == null) { print('产品数据为空'); return; } final actif = productMap['Actif'] as int? ?? 0; final afficheQte = productMap['AfficheQte'] as int? ?? 0; final article = productMap['Article'] as String? ?? ''; // 这里就可以用这些数据更新UI或者做业务逻辑了 print('获取到产品:编号$article,激活状态:${actif == 1 ? "已激活" : "未激活"}'); }
3. 进阶:用实体类+工厂方法简化解析
如果项目里这类动态结构很多,建议给每个action对应的datas子结构写实体类,用工厂方法封装解析逻辑,避免到处写类型转换代码,也更安全。
比如针对getProduct的Product实体类:
class Product { final int actif; final int afficheQte; final String article; Product({ required this.actif, required this.afficheQte, required this.article, }); // 从Map解析成Product的工厂方法 factory Product.fromJson(Map<String, dynamic> json) { return Product( actif: json['Actif'] as int? ?? 0, afficheQte: json['AfficheQte'] as int? ?? 0, article: json['Article'] as String? ?? '', ); } }
然后在处理函数里就可以简化成:
void _handleGetProduct(Map<String, dynamic> datas) { final result = datas['result'] as String?; if (result != 'success') { print('获取产品失败:$result'); return; } final product = Product.fromJson(datas['product'] as Map<String, dynamic>); // 直接用product对象的属性就行 print('产品编号:${product.article}'); }
4. 避坑小贴士
- 处理空值:服务器返回的JSON可能缺失字段,一定要用
??给默认值,或者先判断是否为null,避免类型转换崩溃。 - 数字类型兼容:服务器返回的数字可能是
int或double,可以用num类型先接收,再转成需要的类型(比如cbackId?.toInt())。 - 异常捕获:解析JSON的过程一定要放在
try-catch里,避免单个无效消息导致整个WebSocket连接逻辑崩溃。
内容的提问来源于stack exchange,提问作者Nato Boram
相关产品推荐
相关产品推荐

