Flutter调用API遇类型错误:List<dynamic>无法转为CustomerElement
解决Flutter API解析时的类型不匹配错误
问题场景
我正在用Flutter测试API工作流,用Obx包裹Card组件来基于API数据构建卡片。在这段代码处报错:
return CardList(customer: customerController.customerList[index];
抛出异常:
_TypeError (type 'List
' is not a subtype of type 'CustomerElement')
调试时能看到customerList里已经有JSON数据,怀疑是模型定义的问题,但不确定。
API响应格式
后端返回的JSON结构如下:
[ [ { "customer_id": 1, "customer_title": "m", "customer_fname": "john", "customer_lname": "doe", "customer_email": "johndoe@mail.com", "customer_password": "john" }, { "customer_id": 2, "customer_title": "f", "customer_fname": "jane", "customer_lname": "doe", "customer_email": "jane@female.com", "customer_password": "jane1234" } ], { "fieldCount": 0, "affectedRows": 0, "insertId": 0, "serverStatus": 34, "warningCount": 0, "message": "", "protocol41": true, "changedRows": 0 } ]
当前使用的模型代码(通过quicktype生成)
// To parse this JSON data, do // // final customer = customerFromJson(jsonString); import 'dart:convert'; List<dynamic> customerFromJson(String str) => List<dynamic>.from(json.decode(str).map((x) => x)); String customerToJson(List<dynamic> data) => json.encode(List<dynamic>.from(data.map((x) => x))); class CustomerElement { CustomerElement({ required this.customerId, required this.customerTitle, required this.customerFname, required this.customerLname, required this.customerEmail, required this.customerPassword, }); int customerId; String customerTitle; String customerFname; String customerLname; String customerEmail; String customerPassword; factory CustomerElement.fromJson(Map<String, dynamic> json) => CustomerElement( customerId: json["customer_id"], customerTitle: json["customer_title"], customerFname: json["customer_fname"], customerLname: json["customer_lname"], customerEmail: json["customer_email"], customerPassword: json["customer_password"], ); Map<String, dynamic> toJson() => { "customer_id": customerId, "customer_title": customerTitle, "customer_fname": customerFname, "customer_lname": customerLname, "customer_email": customerEmail, "customer_password": customerPassword, }; } class PurpleCustomer { PurpleCustomer({ required this.fieldCount, required this.affectedRows, required this.insertId, required this.serverStatus, required this.warningCount, required this.message, required this.protocol41, required this.changedRows, }); int fieldCount; int affectedRows; int insertId; int serverStatus; int warningCount; String message; bool protocol41; int changedRows; factory PurpleCustomer.fromJson(Map<String, dynamic> json) => PurpleCustomer( fieldCount: json["fieldCount"], affectedRows: json["affectedRows"], insertId: json["insertId"], serverStatus: json["serverStatus"], warningCount: json["warningCount"], message: json["message"], protocol41: json["protocol41"], changedRows: json["changedRows"], ); Map<String, dynamic> toJson() => { "fieldCount": fieldCount, "affectedRows": affectedRows, "insertId": insertId, "serverStatus": serverStatus, "warningCount": warningCount, "message": message, "protocol41": protocol41, "changedRows": changedRows, }; }
HTTP请求代码
class RemoteService { static var client = http.Client(); static Future<List<dynamic>?> fetchCustomer() async { var url = Uri.parse('http://10.0.2.2:8000/test/getcustomer'); var response = await client.get(url); if (response.statusCode == 200) { var jsonString = response.body; return customerFromJson(jsonString); } else { return null; } } }
问题原因及解决方案
问题根源
API返回的是双层数组+对象的复合结构:
- 第一个元素是包含客户数据的数组
[{}, {}] - 第二个元素是数据库操作的元数据对象
当前解析逻辑直接把整个响应转成List<dynamic>,导致customerList[index]取到的是第一层的客户数组,而非单个CustomerElement对象,因此触发类型不匹配错误。
修复步骤
- 修改模型的解析函数,精准提取客户数据数组:
// 替换原来的customerFromJson函数 List<CustomerElement> customerFromJson(String str) { final decoded = json.decode(str); // 取响应中的第一个元素(客户数组),转换为CustomerElement列表 return List<CustomerElement>.from( (decoded[0] as List).map((x) => CustomerElement.fromJson(x)) ); } // 同步调整toJson函数(按需使用) String customerToJson(List<CustomerElement> data) => json.encode( List<dynamic>.from(data.map((x) => x.toJson())) );
- 更新RemoteService的返回类型,明确返回
List<CustomerElement>?:
class RemoteService { static var client = http.Client(); static Future<List<CustomerElement>?> fetchCustomer() async { var url = Uri.parse('http://10.0.2.2:8000/test/getcustomer'); var response = await client.get(url); if (response.statusCode == 200) { var jsonString = response.body; return customerFromJson(jsonString); } else { return null; } } }
- 确保Controller中的列表类型正确
如果使用GetX,Controller内的customerList需定义为:
final customerList = <CustomerElement>[].obs;
修改完成后,customerController.customerList[index]将返回单个CustomerElement对象,完全匹配CardList组件的参数要求,类型错误即可解决。
内容的提问来源于stack exchange,提问作者Khilesh Emrith
相关产品推荐
相关产品推荐

