Flutter中如何从JSON生成列表并传递给自定义BreakfastCard组件
Flutter本地JSON解析及横向列表实现方案
前置前提
默认你已在项目中添加本地JSON文件到资源目录,且已完成BreakfastCard的基础UI布局开发。
问题1:isPopular判断报"Conditions must have a static type of 'bool'"错误
原因
JSON解析后字段默认是dynamic类型,未明确声明为bool类型,直接用于条件判断触发类型校验失败。
修复方案
定义强类型Breakfast模型类,解析时明确指定字段类型并做空值兜底:
class Breakfast { final String name; final String imagePath; final bool isPopular; // 可根据需求补充其他字段 Breakfast({ required this.name, required this.imagePath, required this.isPopular, }); factory Breakfast.fromJson(Map<String, dynamic> json) { return Breakfast( name: json['name'] as String? ?? '', imagePath: json['imagePath'] as String? ?? '', // 明确转bool类型,空值默认设为false避免异常 isPopular: json['isPopular'] as bool? ?? false, ); } }
问题2:传参报"The argument type 'String' can't be assigned to the parameter type 'Breakfast'"错误
原因
BreakfastCard组件声明的入参是Breakfast实体类型,调用时传入了单独的字符串字段导致类型不匹配。
修复方案
确认BreakfastCard的入参声明为Breakfast类型,调用时直接传实体:
class BreakfastCard extends StatelessWidget { final Breakfast breakfast; const BreakfastCard({super.key, required this.breakfast}); @override Widget build(BuildContext context) { // 原有布局逻辑直接通过breakfast.xxx取对应字段即可 return Container( margin: const EdgeInsets.only(right: 16), width: 120, child: Column( children: [ Image.asset(breakfast.imagePath, height: 100, fit: BoxFit.cover), const SizedBox(height: 8), Text(breakfast.name), ], ), ); } }
问题3:解析得到的items数组无法在List.generate中正常调用
原因
解析后的items默认是dynamic类型数组,未转为List<Breakfast>强类型数组,无法直接遍历生成组件。
修复步骤
- 首先在
pubspec.yaml中声明JSON资源路径:
flutter: assets: - assets/data/breakfast.json # 替换为你的实际JSON文件路径
- 封装JSON读取、解析、筛选逻辑:
import 'dart:convert'; import 'package:flutter/services.dart'; Future<List<Breakfast>> getPopularBreakfasts() async { // 读取本地JSON文件 final jsonStr = await rootBundle.loadString('assets/data/breakfast.json'); final jsonData = json.decode(jsonStr); // 转强类型列表 List<Breakfast> allItems = (jsonData['items'] as List).map((item) => Breakfast.fromJson(item)).toList(); // 筛选isPopular为true的条目 return allItems.where((item) => item.isPopular).toList(); }
- 用FutureBuilder渲染横向滚动列表:
Widget buildPopularBreakfastSection() { return FutureBuilder<List<Breakfast>>( future: getPopularBreakfasts(), builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.done && snapshot.hasData) { final popularList = snapshot.data!; return SizedBox( height: 160, // 按需调整卡片高度 child: ListView.builder( scrollDirection: Axis.horizontal, padding: const EdgeInsets.symmetric(horizontal: 16), itemCount: popularList.length, itemBuilder: (context, index) { return BreakfastCard(breakfast: popularList[index]); }, ), ); } else if (snapshot.hasError) { return const Text('数据加载失败'); } return const CircularProgressIndicator(); }, ); }
注意事项
- JSON文件中
isPopular字段直接写true/false布尔值,不要加引号变成字符串类型 - 所有JSON解析步骤都要做类型转换和空值兜底,避免运行时异常
内容的提问来源于stack exchange,提问作者Gheh
相关产品推荐
相关产品推荐

