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

如何在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 11:25:56