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

Flutter中如何将Object类型JSON数据渲染为ListView

Flutter渲染Object类型JSON到ListView问题解决

问题描述

之前能正常将数组类型JSON数据渲染为ListView,但当前API返回Object类型JSON。通过API调用已获取到Map<String, DataKuliahModel>格式的数据,且有对应的DataKuliahModel模型,但初始化数据并渲染到ListView时出错,寻求解决方法。

API调用代码

static Future<Map<String, DataKuliahModel>> getDataKuliah(int smt) async {
    String url = Constant.baseURL;
    String token = await UtilSharedPreferences.getToken();
    await Future.delayed(const Duration(milliseconds: 1000));

    Map<String, DataKuliahModel> finalResult = {};
    final response = await http.get(
      Uri.parse(
        '$url/auth/mhs_siakad/perwalian/get_paket?smt=$smt',
      ),
      headers: {
        'Authorization': 'Bearer $token',
      },
    );
    print(response.statusCode);
    print(response.body);
    final result = jsonDecode(response.body)['data'] as Map<String, dynamic>;
    result.forEach((key, value) {
      DataKuliahModel dataKuliah = DataKuliahModel.fromMap(value);
      finalResult.addAll({
        key: dataKuliah,
      });
    });
    return finalResult;
  }

DataKuliahModel模型代码

class DataKuliahModel {
  DataKuliahModel({
    this.id = '',
    this.idDosen = '',
    this.idMk = '',
    this.nidn,
    this.dosen = '',
    this.idKelasKuliah = '',
    this.kelasKuliah = '',
    this.prodi = '',
    this.kelas = '',
    this.semester = '',
    this.kelompokKelas = '',
    this.kode,
    this.sks = 0,
    this.jumlahKelas = 0,
    this.matakuliah = '',
    this.smt = '',
    this.bobotSks = 0,
    this.rencanaPertemuan = 0,
    this.jenisEvaluasi = '',
  });

  String id;
  String idDosen;
  String idMk;
  dynamic nidn;
  String dosen;
  String idKelasKuliah;
  String kelasKuliah;
  String prodi;
  String kelas;
  String semester;
  String kelompokKelas;
  dynamic kode;
  int sks;
  int jumlahKelas;
  String matakuliah;
  String smt;
  int bobotSks;
  int rencanaPertemuan;
  String jenisEvaluasi;

  factory DataKuliahModel.fromJson(String str) =>
      DataKuliahModel.fromMap(json.decode(str));

  String toJson() => json.encode(toMap());

  factory DataKuliahModel.fromMap(Map<String, dynamic> json) => DataKuliahModel(
        id: json["id"] ?? '',
        idDosen: json["id_dosen"] ?? '',
        idMk: json["id_mk"] ?? '',
        nidn: json["nidn"],
        dosen: json["dosen"] ?? '',
        idKelasKuliah: json["id_kelas_kuliah"] ?? '',
        kelasKuliah: json["kelas_kuliah"] ?? '',
        prodi: json["prodi"] ?? '',
        kelas: json["kelas"] ?? '',
        semester: json["semester"] ?? '',
        kelompokKelas: json["kelompok_kelas"] ?? '',
        kode: json["kode"],
        sks: json["sks"] ?? 0,
        jumlahKelas: json["jumlah_kelas"] ?? 0,
        matakuliah: json["matakuliah"] ?? '',
        smt: json["smt"] ?? '',
        bobotSks: json["bobot_sks"] ?? 0,
        rencanaPertemuan: json["rencana_pertemuan"] ?? 0,
        jenisEvaluasi: json["jenis_evaluasi"] ?? '',
      );

  Map<String, dynamic> toMap() => {
        "id": id,
        "id_dosen": idDosen,
        "id_mk": idMk,
        "nidn": nidn,
        "dosen": dosen,
        "id_kelas_kuliah": idKelasKuliah,
        "kelas_kuliah": kelasKuliah,
        "prodi": prodi,
        "kelas": kelas,
        "semester": semester,
        "kelompok_kelas": kelompokKelas,
        "kode": kode,
        "sks": sks,
        "jumlah_kelas": jumlahKelas,
        "matakuliah": matakuliah,
        "smt": smt,
        "bobot_sks": bobotSks,
        "rencana_pertemuan": rencanaPertemuan,
        "jenis_evaluasi": jenisEvaluasi,
      };
}

JSON响应示例

JSON响应

初始化出错位置

初始化错误

解决方法

1. 数据类型适配与转换

ListView需要Iterable类型数据,而你拿到的是Map,所以需要将Map的value集合转成List:

// 使用FutureBuilder处理异步数据
FutureBuilder<Map<String, DataKuliahModel>>(
  future: ApiService.getDataKuliah(1), // 传入对应学期参数
  builder: (context, snapshot) {
    if (snapshot.connectionState == ConnectionState.done) {
      if (snapshot.hasData) {
        // 将Map的values转为List,供ListView使用
        final List<DataKuliahModel> kuliahList = snapshot.data!.values.toList();
        return ListView.builder(
          itemCount: kuliahList.length,
          itemBuilder: (context, index) {
            final item = kuliahList[index];
            return ListTile(
              title: Text(item.matakuliah),
              subtitle: Text('授课教师:${item.dosen} | SKS:${item.sks}'),
            );
          },
        );
      } else if (snapshot.hasError) {
        return Center(child: Text('加载失败:${snapshot.error}'));
      }
    }
    return const Center(child: CircularProgressIndicator());
  },
)

2. 修正状态变量类型

从错误截图看,大概率是变量类型不匹配(比如用List接收Map数据)。确保状态变量类型与API返回一致:

// 定义状态变量
late Map<String, DataKuliahModel> _kuliahData;

@override
void initState() {
  super.initState();
  _loadData();
}

// 异步加载数据
Future<void> _loadData() async {
  _kuliahData = await ApiService.getDataKuliah(1);
  setState(() {});
}

// 构建UI时转成List使用
@override
Widget build(BuildContext context) {
  return Scaffold(
    body: _kuliahData.isEmpty 
        ? const Center(child: CircularProgressIndicator())
        : ListView.builder(
            itemCount: _kuliahData.values.length,
            itemBuilder: (context, index) {
              final item = _kuliahData.values.toList()[index];
              return ListTile(title: Text(item.matakuliah));
            },
          ),
  );
}

3. 保留Map键信息(可选)

如果需要用到JSON里的键(如示例中的"1"、"2"),可以将Map转成MapEntry列表:

final List<MapEntry<String, DataKuliahModel>> entries = _kuliahData.entries.toList();
// 在itemBuilder中获取键和值
final entry = entries[index];
String itemKey = entry.key;
DataKuliahModel itemValue = entry.value;

内容的提问来源于stack exchange,提问作者sharon

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 11:30:50