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

Flutter技术问题:如何根据product_key从对象模型提取对应Map

问题:根据product_key提取对应Map并生成Flutter Widget列表

一、初始场景与疑问

我有一个返回List<GoodsModel>格式数据的模型,示例数据如下:

[ GoodsModel(id: 483, productCategory: sport, productType: t-shirt, productDisplayName: Shirt, product_key: sport_goods, productRecommendation: null, sport_goods: {id: 12, name: t-shirt colored, color: blue}) ]

其中product_key的值(如sport_goods)与对应的Map键名完全一致。我想根据product_key提取对应的Map(比如示例中的sport_goods),写了初始代码但不确定return部分如何编写:

var myMap = goodsList.map((e) {
        if (e.product_key == 'sport_goods') {
          return ???;
        }
      });

二、Flutter代码问题(生成Widget列表)

我的最终目标是基于提取出的Map生成Widget列表,尝试编写的代码存在问题,希望得到解决:

import 'package:flutter/material.dart';

class GoodsList extends StatefulWidget {
  const GoodsList({super.key});

  @override
  State<GoodsList> createState() => _GoodsListState();
}

class _GoodsListState extends State<GoodsList> {
  // Data sample
  var data = {
    "id": 483,
    "productCategory": "sport",
    "productType": "t-shirt",
    "productDisplayName": "Shirt",
    "product_key": "sport_goods", // (2) based on this value
    "productRecommendation": null,
  // (1) I need to get this data
    "sport_goods": {
      "id": 12,
      "name": "t-shirt colored",
      "color": "blue",
    }
  };

  @override
  Widget build(BuildContext context) {
    for (var i = 0; i < data.length; i++) {
      // (3) how to get the piece of map in here???
      if (data[i]!['product_key'] == 'sport_goods') {
        return Column(
          children: [
            Text(data[i]!['sport_goods']!['id']),
            Text(data[i]!['sport_goods']!['name']),
            Text(data[i]!['sport_goods']!['color']),
          ],
        ) // This is the problem I believe
      }
    }

    return const Text('No data');
  }
}

解决方案

一、从GoodsModel中提取对应Map

方法1:添加模型方法(推荐,无反射)

在GoodsModel类中新增一个方法,直接根据product_key返回对应的Map:

class GoodsModel {
  // 原有的字段和构造方法
  final int id;
  final String productCategory;
  final String productType;
  final String productDisplayName;
  final String product_key;
  final Map<String, dynamic>? sport_goods;
  // 其他可能的商品类型Map字段

  GoodsModel({
    required this.id,
    required this.productCategory,
    required this.productType,
    required this.productDisplayName,
    required this.product_key,
    this.sport_goods,
    // 其他字段的构造参数
  });

  // 新增方法:获取对应商品详情Map
  Map<String, dynamic>? getProductMap() {
    switch(product_key) {
      case 'sport_goods':
        return sport_goods;
      // 如果有其他product_key类型,添加对应的case
      default:
        return null;
    }
  }
}

之后你的初始代码可以这样写:

// 过滤并提取符合条件的Map,移除null值
var myMapList = goodsList
    .map((e) => e.getProductMap())
    .whereType<Map<String, dynamic>>()
    .toList();

方法2:通过toJson转换(动态适配多类型)

如果GoodsModel有toJson方法(通常由json_serializable生成),可以转成Map后通过product_key动态取值:

var myMapList = goodsList.map((e) {
  if (e.product_key == 'sport_goods') {
    final modelMap = e.toJson();
    return modelMap[e.product_key] as Map<String, dynamic>?;
  }
  return null;
}).whereType<Map<String, dynamic>>().toList();

二、修正Flutter代码生成Widget列表

你的原有代码存在3个核心问题:

  1. data是单个Map而非List,无法通过索引遍历多个商品
  2. build方法中循环直接return会终止渲染,只能返回第一个匹配项
  3. Text组件接收的数字类型未转成字符串

修正后的完整代码:

import 'package:flutter/material.dart';

class GoodsList extends StatefulWidget {
  const GoodsList({super.key});

  @override
  State<GoodsList> createState() => _GoodsListState();
}

class _GoodsListState extends State<GoodsList> {
  // 修正为List存储多商品数据
  List<Map<String, dynamic>> data = [
    {
      "id": 483,
      "productCategory": "sport",
      "productType": "t-shirt",
      "productDisplayName": "Shirt",
      "product_key": "sport_goods",
      "productRecommendation": null,
      "sport_goods": {
        "id": 12,
        "name": "t-shirt colored",
        "color": "blue",
      }
    },
    // 可以添加更多商品数据
  ];

  @override
  Widget build(BuildContext context) {
    // 过滤符合条件的商品,并提取对应的详情Map
    final validProductMaps = data
        .where((item) => item['product_key'] == 'sport_goods')
        .map((item) {
          // 动态根据product_key提取对应Map
          return item[item['product_key']] as Map<String, dynamic>;
        })
        .toList();

    if (validProductMaps.isEmpty) {
      return const Center(child: Text('No data'));
    }

    // 生成Widget列表(用ListView避免溢出)
    return ListView.builder(
      padding: const EdgeInsets.all(16),
      itemCount: validProductMaps.length,
      itemBuilder: (context, index) {
        final product = validProductMaps[index];
        return Card(
          margin: const EdgeInsets.only(bottom: 12),
          child: Padding(
            padding: const EdgeInsets.all(12),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Text('ID: ${product['id']}'),
                const SizedBox(height: 4),
                Text('名称: ${product['name']}'),
                const SizedBox(height: 4),
                Text('颜色: ${product['color']}'),
              ],
            ),
          ),
        );
      },
    );
  }
}

关键优化点说明:

  • 将data改为List<Map<String, dynamic>>,支持多商品数据
  • 先过滤并提取目标Map,再通过ListView.builder生成列表,避免单次return终止渲染
  • 动态使用item[item['product_key']]获取对应Map,无需硬编码键名
  • 将数字类型的id转为字符串后传入Text组件,避免类型错误
  • 使用Card和Padding优化UI布局,提升可读性

内容的提问来源于stack exchange,提问作者kalibear

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 22:27:05