Flutter动态JSON展示:如何并列显示AppDetails的键与对应数据
Flutter动态展示appDetails下所有键值对的实现示例
核心思路
因为appDetails的键是动态变化的,但字段本身固定存在,所以可以将其转为Map<String, dynamic>后,遍历所有键值对,根据值的类型(字符串、列表等)动态渲染对应的UI组件。
示例代码
以下是完整的可运行示例,包含模拟数据、键名格式化、多类型值渲染:
import 'package:flutter/material.dart'; void main() => runApp(const MyApp()); class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar(title: const Text('App Details展示')), body: const AppDetailsView(), ), ); } } class AppDetailsView extends StatelessWidget { const AppDetailsView({super.key}); // 模拟接口返回的动态JSON数据 final Map<String, dynamic> productData = { "productName": "智能办公系统", "appDetails": { "systemOverview": "这是一套集成了文档管理、协作沟通的智能办公平台,提升团队效率。", "benefits": ["降低沟通成本", "提升文档安全性", "简化审批流程"], "mainFeatures": ["实时协作编辑", "多级权限管理", "跨设备同步"], "usageScenarios": "适用于中小团队、企业远程办公、项目协作等场景" } }; @override Widget build(BuildContext context) { // 提取appDetails核心数据 final Map<String, dynamic> appDetails = productData['appDetails']; return Padding( padding: const EdgeInsets.all(16.0), // 用ListView实现滚动展示 child: ListView.builder( itemCount: appDetails.entries.length, itemBuilder: (context, index) { final entry = appDetails.entries.elementAt(index); final key = entry.key; final value = entry.value; return Padding( padding: const EdgeInsets.only(bottom: 20.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // 格式化后的键名标题 Text( _formatKeyName(key), style: const TextStyle( fontSize: 18, fontWeight: FontWeight.bold, color: Colors.blueAccent, ), ), const SizedBox(height: 8), // 根据值类型渲染对应组件 _buildValueWidget(value), ], ), ); }, ), ); } // 将驼峰命名的键转为友好的标题(如systemOverview → 系统概述) String _formatKeyName(String key) { final formatted = key.replaceAllMapped( RegExp(r'([A-Z])'), (match) => ' ${match.group(0)}', ); return formatted[0].toUpperCase() + formatted.substring(1); } // 根据值的类型返回对应UI组件 Widget _buildValueWidget(dynamic value) { if (value is List) { // 列表类型渲染带项目符号的列表 return Column( crossAxisAlignment: CrossAxisAlignment.start, children: value.map((item) { return Padding( padding: const EdgeInsets.symmetric(vertical: 4.0), child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text('• ', style: TextStyle(fontSize: 16)), Expanded(child: Text(item.toString(), style: const TextStyle(fontSize: 16))), ], ), ); }).toList(), ); } else if (value is String) { // 字符串类型直接展示 return Text(value, style: const TextStyle(fontSize: 16, height: 1.5)); } else { // 其他类型(数字、布尔值等)转为字符串展示 return Text(value.toString(), style: const TextStyle(fontSize: 16)); } } }
关键说明
- 遍历键值对:通过
appDetails.entries获取所有键值对,用ListView.builder动态生成每一项 - 键名格式化:
_formatKeyName方法将驼峰命名的键转为易读的标题,可根据需求调整格式规则 - 多类型适配:
_buildValueWidget方法根据值的类型(列表、字符串等)渲染不同UI,若有嵌套Map等复杂结构,可在此方法中添加递归处理逻辑 - 异步数据适配:如果数据来自网络请求,只需将示例中的模拟数据替换为
FutureBuilder或状态管理中的异步数据即可
扩展提示
- 可根据设计需求添加卡片容器、阴影、自定义间距等样式优化
- 若需支持更多数据类型(如嵌套对象),只需在
_buildValueWidget中新增对应类型的处理分支
内容的提问来源于stack exchange,提问作者Talal Habib
相关产品推荐
相关产品推荐

