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

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);
  }
}

解决方案

问题根源分析

  1. 模型字段不匹配:APIDataGrouped的fromJson/toJson使用classname_作为列表字段名,与目标JSON的apidata_不一致,导致解析错误。
  2. 错误的合并逻辑:d.reduce(...)将多个分组Map合并为单个Map,完全违背分组后是列表的需求。
  3. 返回类型错误: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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 15:15:39