Flutter中如何将JSON对象数组转换为带分组的List<Map<String, dynamic>>
Dart JSON分组转换问题:从List到分组后的List
原始JSON结构
{ "apidata_": [ {"id":1, "string_":"a", "groupedString_":"G1"}, {"id":2, "string_":"b", "groupedString_":"G2"}, {"id":3, "string_":"c", "groupedString_":"G2"} ] }
目标分组后JSON结构
[ { "groupedString_":"G1", "apidata_":[ {"id":1,"string_":"a"} ] }, { "groupedString_":"G2", "apidata_":[ {"id":2,"string_":"b"}, {"id":3,"string_":"c"} ] } ]
原始JSON对应模型类
class ListOfAPIData { ListOfAPIData({required this.apidata_}); List<APIData> apidata_; factory ListOfAPIData.fromJson(Map<String, dynamic> json) => ListOfAPIData( apidata_: List<APIData>.from(json['apidata_'].map((e) => APIData.fromJson(e)))); Map<String, dynamic> toJson() => {"data": List<dynamic>.from(apidata_.map((e) => e.toJson()))}; } class APIData { APIData({ required this.id_, required this.string_, required this.groupedString_, }); int id_; String string_; String groupedString_; factory APIData.fromJson(Map<String, dynamic> json) => APIData( id_: json["id_"], string_: json["string_"], groupedString_: json["groupedString_"]); Map<String, dynamic> toJson() => {"id_": id_, "string_": string_, "groupedString_": groupedString_}; }
分组后数据模型类
class APIDataGrouped { APIDataGrouped({required this.groupedString_, required this.apidata_}); String? groupedString_; List<APIData>? apidata_; factory APIDataGrouped.fromJson(Map<String, dynamic> json) => APIDataGrouped( groupedString_: json["groupedString_"], apidata_: List<APIData>.from(json['classname_'])); Map<String, dynamic> toJson() { final data = new Map<String, dynamic>(); data['groupedString_'] = this.groupedString_; data['classname_'] = this.apidata_!.map((e) => e.toJson()).toList(); return data; } }
问题描述
尝试将JSON对象数组转换为List<Map<String, dynamic>>类型(其中dynamic部分为List<Object>),已使用groupBy()生成对应结构,但后续遇到多个错误:
List<dynamic> is not a subtype of <Map<String, dynamic>>FormatException: unexpected character
核心问题:APIDataGrouped构造函数仅接受Map<String, dynamic>参数,无法正确传入分组后的列表数据。
现有API请求处理类代码
class CallAPI { Future<ListOfAPIData> fetchdata() async { final respon = await get(Uri.http("serverAPI", '/path/of/API')); final body = jsonDecode(respon.body); final ListOfAPIData data; if (respon.statusCode == 200 && body != null) { data = ListOfAPIData.fromJson(body); return data; } else { throw "error"; } } Future<APIDataGrouped> datagrouped() async { var data = await fetchdata(); final g = groupBy( data.apidata_, (p0) => (p0 as APIData).groupedString_, ); final d = <Map<String, dynamic>>[]; g.forEach((key, value) { d.add({ "groupedString_": key, "apidata_": value .map((e) => Map.from(e.toJson())..remove('groupedString_')) .toList() }); }); final datafinal = d.reduce((value, element) { value.addAll(element); return value; }); return APIDataGrouped.fromJson(datafinal); } }
解决方案
问题根源分析
- 模型字段不匹配:
APIDataGrouped的fromJson/toJson使用classname_作为列表字段名,与目标JSON的apidata_不一致,导致解析错误。 - 错误的合并逻辑:
d.reduce(...)将多个分组Map合并为单个Map,完全违背分组后是列表的需求。 - 返回类型错误:
datagrouped方法返回单个APIDataGrouped,但分组结果应为多个分组对象的列表。
修正后的代码
1. 修正APIDataGrouped模型类
统一字段名与目标JSON对齐:
class APIDataGrouped { APIDataGrouped({required this.groupedString_, required this.apidata_}); String groupedString_; List<APIData> apidata_; factory APIDataGrouped.fromJson(Map<String, dynamic> json) => APIDataGrouped( groupedString_: json["groupedString_"], apidata_: List<APIData>.from(json['apidata_'].map((e) => APIData.fromJson(e))), ); Map<String, dynamic> toJson() => { "groupedString_": groupedString_, "apidata_": apidata_.map((e) => { "id_": e.id_, "string_": e.string_, }).toList(), }; }
2. 修正CallAPI的datagrouped方法
返回分组后的列表,移除错误的合并逻辑:
class CallAPI { Future<ListOfAPIData> fetchdata() async { final respon = await get(Uri.http("serverAPI", '/path/of/API')); final body = jsonDecode(respon.body); if (respon.statusCode == 200 && body != null) { return ListOfAPIData.fromJson(body); } else { throw Exception("请求失败"); } } Future<List<APIDataGrouped>> datagrouped() async { var data = await fetchdata(); // 按groupedString_分组 final groupedMap = groupBy( data.apidata_, (APIData item) => item.groupedString_, ); // 将分组Map转换为List<APIDataGrouped> return groupedMap.entries.map((entry) { final groupKey = entry.key; final groupItems = entry.value; // 移除每个item的groupedString_字段 final filteredItems = groupItems.map((item) => APIData( id_: item.id_, string_: item.string_, groupedString_: '', // 若不需要该字段,可创建简化模型类 )).toList(); return APIDataGrouped( groupedString_: groupKey, apidata_: filteredItems, ); }).toList(); } }
3. 额外优化建议
如果不需要保留APIData中的groupedString_字段,可创建简化模型类(如APIDataItem),仅包含id_和string_,更贴合目标JSON结构。
内容的提问来源于stack exchange,提问作者pras
相关产品推荐
相关产品推荐

