Flutter/Dart中如何将指定JSON解析为类对象并用于多级下拉菜单
Flutter/Dart 多级下拉菜单实现方案
第一步:JSON转Dart模型类
首先将目标JSON结构映射为可复用的Dart类,同时编写解析方法:
// 车型模型类 class CarModel { final String model; final int doors; CarModel({required this.model, required this.doors}); factory CarModel.fromJson(Map<String, dynamic> json) { return CarModel( model: json['model'], doors: json['doors'], ); } } // JSON解析方法,返回格式为「品牌名: 对应车型列表」的映射 Map<String, List<CarModel>> parseCarJson(Map<String, dynamic> json) { final carsJson = json['cars'] as Map<String, dynamic>; Map<String, List<CarModel>> result = {}; carsJson.forEach((brand, modelsList) { List<CarModel> models = (modelsList as List).map((e) => CarModel.fromJson(e)).toList(); result[brand] = models; }); return result; }
第二步:多级下拉完整实现
二级下拉逻辑为:第一级选汽车品牌,第二级联动展示对应品牌下的车型,未选品牌时车型下拉默认禁用:
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('汽车多级下拉示例')), body: const CarDropdownPage(), ), ); } } class CarDropdownPage extends StatefulWidget { const CarDropdownPage({super.key}); @override State<CarDropdownPage> createState() => _CarDropdownPageState(); } class _CarDropdownPageState extends State<CarDropdownPage> { // 解析后的汽车数据源 Map<String, List<CarModel>> carData = {}; // 选中状态存储 String? selectedBrand; CarModel? selectedModel; @override void initState() { super.initState(); // 模拟接口返回的JSON数据,实际使用替换为真实接口返回值即可 final mockJson = { "cars": { "Nissan": [ {"model": "Sentra", "doors":4}, {"model": "Maxima", "doors":4}, {"model": "Skyline", "doors":2} ], "Ford": [ {"model": "Taurus", "doors":4}, {"model": "Escort", "doors":4} ] } }; carData = parseCarJson(mockJson); } @override Widget build(BuildContext context) { return Padding( padding: const EdgeInsets.all(20), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // 第一级:品牌下拉 const Text('选择品牌:'), DropdownButton<String>( value: selectedBrand, hint: const Text('请选择品牌'), isExpanded: true, items: carData.keys.map((brand) { return DropdownMenuItem( value: brand, child: Text(brand), ); }).toList(), onChanged: (value) { setState(() { selectedBrand = value; // 切换品牌时清空已选车型,避免状态异常 selectedModel = null; }); }, ), const SizedBox(height: 30), // 第二级:车型下拉 const Text('选择车型:'), DropdownButton<CarModel>( value: selectedModel, hint: selectedBrand == null ? const Text('请先选择品牌') : const Text('请选择车型'), isExpanded: true, // 未选品牌时设置onChanged为null,直接禁用下拉 onChanged: selectedBrand == null ? null : (value) { setState(() { selectedModel = value; }); }, items: selectedBrand == null ? [] : carData[selectedBrand]!.map((model) { return DropdownMenuItem( value: model, child: Text('${model.model}(${model.doors}门)'), ); }).toList(), ), const SizedBox(height: 30), // 选中结果展示 if (selectedModel != null) Text('已选车辆:$selectedBrand ${selectedModel!.model},${selectedModel!.doors}门'), ], ), ); } }
核心逻辑说明
- 品牌下拉选项直接从解析后数据源的key映射生成,不需要额外处理映射关系
- 车型下拉的选项完全依赖选中的品牌动态生成,状态联动逻辑全部放在
setState中处理 - 每个
DropdownMenuItem的value直接绑定对应的数据对象,取值时不需要额外做索引匹配
内容的提问来源于stack exchange,提问作者jagan V026
相关产品推荐
相关产品推荐

