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响应示例

初始化出错位置

解决方法
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
相关产品推荐
相关产品推荐

