如何在Flutter中将含数组键的JSON数组转为ExpansionTile列表
解决JSON转换为ExpansionTile列表的问题
原代码存在的核心问题
- 变量名不匹配:解析后得到
tags,但循环时用了未定义的bookList - 类型不安全:直接使用
List<dynamic>,未转换成具体实体类,导致属性访问报错 - 拼写错误:
chrildren应为children,<Widgets>应为<Widget> - 错误的列表项展示:直接将
j(OwnerHistory对象)传给Text,会打印对象实例而非具体字段 - 空值处理不当:
List.from(tagsJson) : null会导致类型不匹配,null无法赋值给List<dynamic>
完整解决方案
第一步:创建数据模型类
定义对应JSON结构的实体类,保证类型安全:
class Book { final String bookName; final List<OwnerHistory> ownerHistory; Book({required this.bookName, required this.ownerHistory}); // 手动实现fromJson方法(也可使用json_serializable简化) factory Book.fromJson(Map<String, dynamic> json) { var ownerHistoryList = json['Ownerhistory'] as List; List<OwnerHistory> owners = ownerHistoryList .map((ownerJson) => OwnerHistory.fromJson(ownerJson)) .toList(); return Book( bookName: json['bookName'], ownerHistory: owners, ); } } class OwnerHistory { final String name; final String address; OwnerHistory({required this.name, required this.address}); factory OwnerHistory.fromJson(Map<String, dynamic> json) { return OwnerHistory( name: json['name'], address: json['address'], ); } }
第二步:修正JSON解析逻辑
将JSON字符串转换成List<Book>,同时处理空值和解析异常:
final jsonStringData = ref.watch(responseProvider); List<Book> bookList = []; if (jsonStringData != null && jsonStringData.isNotEmpty) { try { var decodedList = jsonDecode(jsonStringData) as List; bookList = decodedList.map((item) => Book.fromJson(item)).toList(); } catch (e) { // 处理解析错误,比如打印日志或提示用户 print('JSON解析失败: $e'); } }
第三步:修正ExpansionTile列表构建
修正拼写错误,正确遍历列表并展示字段:
return Column( children: [ for (var book in bookList) ExpansionTile( title: Text(book.bookName), children: [ for (var owner in book.ownerHistory) ListTile( title: Text(owner.name), subtitle: Text(owner.address), // 额外展示地址信息 ) ], ) ], );
完整代码整合
import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; class Book { final String bookName; final List<OwnerHistory> ownerHistory; Book({required this.bookName, required this.ownerHistory}); factory Book.fromJson(Map<String, dynamic> json) { var ownerHistoryList = json['Ownerhistory'] as List; List<OwnerHistory> owners = ownerHistoryList .map((ownerJson) => OwnerHistory.fromJson(ownerJson)) .toList(); return Book( bookName: json['bookName'], ownerHistory: owners, ); } } class OwnerHistory { final String name; final String address; OwnerHistory({required this.name, required this.address}); factory OwnerHistory.fromJson(Map<String, dynamic> json) { return OwnerHistory( name: json['name'], address: json['address'], ); } } class BookScreen extends ConsumerWidget { const BookScreen({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { final jsonStringData = ref.watch(responseProvider); List<Book> bookList = []; if (jsonStringData != null && jsonStringData.isNotEmpty) { try { var decodedList = jsonDecode(jsonStringData) as List; bookList = decodedList.map((item) => Book.fromJson(item)).toList(); } catch (e) { print('JSON解析失败: $e'); } } return Column( children: [ for (var book in bookList) ExpansionTile( title: Text(book.bookName), children: [ for (var owner in book.ownerHistory) ListTile( title: Text(owner.name), subtitle: Text(owner.address), ) ], ) ], ); } } // 假设responseProvider是你定义的Provider final responseProvider = StateProvider<String?>((ref) => null);
内容的提问来源于stack exchange,提问作者DrakeJest
相关产品推荐
相关产品推荐

