Flutter从Django DRF取数遇类型错误:预期List<dynamic>实际为_JsonMap
问题描述
我在Flutter中编写了ListExpected a value of type List<dynamic> but got one type _JsonMap。数据从Django REST Framework以JSON格式获取,后端服务能正常启动,但界面无法展示数据,仅在中心组件显示该错误信息。
我的代码如下:
// ignore_for_file: dead_code, prefer_const_constructors, prefer_const_literals_to_create_immutables, deprecated_member_use, avoid_print, non_constant_identifier_names import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; import 'dart:async'; Future<List<Data>> fetchData() async { var url = Uri.parse('http://127.0.0.1:8000/api/?format=json'); final response = await http.get(url); if (response.statusCode == 200) { // final jSon = "[${response.body}]"; List jsonResponse = (json.decode(response.body) as List<dynamic>); return jsonResponse.map((data) => Data.fromJson(data)).toList(); } else { throw Exception('Unexpected error occured!'); } } class Data { final int ID; final String visitor_name; final String visit_date; final String time_in; final String time_out; final String department; final String visitee_name; final String address; final String phone; final String purpose_of_visit; Data({required this.ID, required this.visitor_name, required this.visit_date, required this.time_in, required this.time_out, required this.department, required this.visitee_name, required this.address, required this.phone, required this.purpose_of_visit}); factory Data.fromJson(Map<String, dynamic> json) { return Data( ID: json['ID'], visitor_name: json['visitor_name'], visit_date: json['visit_date'], time_in: json['time_in'], time_out: json['time_out'], department: json['department'], visitee_name: json['visitee_name'], address: json['address'], phone: json['phone'], purpose_of_visit: json['purpose_of_visit'], ); } } class ViewRecord extends StatefulWidget { const ViewRecord({super.key}); @override State<ViewRecord> createState() => _ViewRecordState(); } class _ViewRecordState extends State<ViewRecord> { @override Widget build(BuildContext context) { return FutureBuilder<List<Data>>( future: fetchData(), builder: (context, snapshot) { if (snapshot.hasData) { return SingleChildScrollView( scrollDirection: Axis.vertical, child: SingleChildScrollView( scrollDirection: Axis.horizontal, child: DataTable( decoration: BoxDecoration( ), border: TableBorder.all( style: BorderStyle.solid, width: 2, borderRadius: BorderRadius.circular(5)), columnSpacing: 50, dataRowHeight: 50, dividerThickness: 2, headingRowColor: MaterialStateProperty.resolveWith((states) => Colors.lightBlue[50]), columns: const <DataColumn>[ DataColumn(label: Text('ID')), DataColumn(label: Text('Visitor\'s Name')), DataColumn(label: Text('Visit Date')), DataColumn(label: Text('Time In')), DataColumn(label: Text('Time Out')), DataColumn(label: Text('Department')), DataColumn(label: Text('Visitee')), DataColumn(label: Text('Address')), DataColumn(label: Text('Phone')), DataColumn(label: Text('Purpose of Visit')), ], rows: List.generate( snapshot.data!.length, (index) { var data = snapshot.data![index]; return DataRow(cells: [ DataCell( Text(data.ID.toString()) ), DataCell( Text(data.visitor_name.toString()) ), DataCell( Text(data.visit_date.toString()) ), DataCell( Text(data.time_in.toString()) ), DataCell( Text(data.time_out.toString()) ), DataCell( Text(data.department.toString()) ), DataCell( Text(data.visitee_name.toString()) ), DataCell( Text(data.address.toString()) ), DataCell( Text(data.phone.toString()) ), DataCell( Text(data.purpose_of_visit.toString()) ), ] ); } ).toList(), ), ), ); } else if (snapshot.hasError) { return Text(snapshot.error.toString()); } return const CircularProgressIndicator(); }, ); } }
解决方案
这个错误的核心原因是后端返回的JSON并非直接的数组(List),而是一个包含数组的对象(_JsonMap)。Django REST Framework默认的列表接口响应通常会包含results字段(比如分页结构),或者你的API返回的顶层结构本身就是对象而非数组。
具体修复步骤:
确认后端JSON结构
先打印后端返回的原始数据,确认结构:print(response.body);常见的Django REST Framework列表响应格式如下:
{ "count": 2, "next": null, "previous": null, "results": [ {"ID": 1, "visitor_name": "示例访客1", ...}, {"ID": 2, "visitor_name": "示例访客2", ...} ] }修改
fetchData的解析逻辑
根据实际的JSON结构,先解析为Map,再取出对应的列表字段。比如针对上面的默认格式,修改代码如下:Future<List<Data>> fetchData() async { var url = Uri.parse('http://127.0.0.1:8000/api/?format=json'); final response = await http.get(url); if (response.statusCode == 200) { // 先将响应解析为Map Map<String, dynamic> responseMap = json.decode(response.body) as Map<String, dynamic>; // 取出results对应的数组 List jsonResponse = responseMap['results'] as List<dynamic>; return jsonResponse.map((data) => Data.fromJson(data)).toList(); } else { throw Exception('Unexpected error occured!'); } }如果你的API返回的是自定义结构,只需将
responseMap['results']中的results替换为实际的列表字段名即可。排查API地址
若确认后端返回的就是单个对象,那可能是请求了详情接口而非列表接口,需要检查API地址是否正确。
内容的提问来源于stack exchange,提问作者Jonathan Kwabena Ewenam Kudiab
相关产品推荐
相关产品推荐

