Flutter/Dart中如何处理HTTP请求内容并将响应转为可用列表?
问题:将HTTP响应体转换为实体类列表并使用变量
打印的HTTP响应体
I/flutter (30828): {"firstName":"Georgee","lastName":"Contructed","userID":256,"month":8,"year":2022,"cardBills":[{"serial":"281929282881","value":4.8150,"vat":1.1556,"total":5.9706,"energy":0},{"serial":"281929282881","value":1.0567,"vat":0.2536,"total":1.3103,"energy":0}],"cardBillsTotal":[{"serial":"281929282881","value":5.8717,"vat":1.4092,"total":7.2809,"energy":0}]}
当前代码实现
页面中的相关方法
initState() { fetch(); } List<Evsebill> parseBills(String responseBody) { final parsed = jsonDecode(responseBody)['cardBills'].cast<Map<String, dynamic>>(); return parsed.map<Evsebill>((json) => Evsebill.fromJson(json)).toList(); } Future<List<Evsebill>> fetch() async { String? token = await this.storage.read(key: "token"); Map<String, String> headers = { "Content-Type": "application/json", "Accept": "application/json", "Authorization": "Bearer " + (token ?? ""), }; final response = await http.get(Uri.parse(this.serverIP + ':' + this.serverPort + '/user/contractedChargeTransactions?month=8&year=2022'), headers: headers); // Use the compute function to run parsePhotos in a separate isolate. print(response.body); return parseBills(response.body); }
Evsebill实体类
class Evsebill { final int serial; final double value; final double vat; final double total; final int energy; const Evsebill({ required this.serial, required this.value, required this.vat, required this.total, required this.energy }); factory Evsebill.fromJson(Map<String, dynamic> json) { return Evsebill( serial: json['serial'] as int, value: json['value']as double, vat: json['vat']as double, total: json['total']as double, energy: json['energy']as int, ); } }
问题分析与修复方案
你的代码会抛出类型转换错误,核心原因是HTTP响应里的serial字段是字符串类型(例如"281929282881"),但实体类中serial定义为int类型,直接强转as int会失败。以下是具体修复和使用方案:
1. 修正实体类的类型转换逻辑
有两种可选方案:
- 方案一:将
serial改为字符串类型(若不需要用该字段做数值计算):class Evsebill { final String serial; // 修改为String类型 final double value; final double vat; final double total; final int energy; const Evsebill({ required this.serial, required this.value, required this.vat, required this.total, required this.energy }); factory Evsebill.fromJson(Map<String, dynamic> json) { return Evsebill( serial: json['serial'] as String, // 对应字符串类型 value: json['value']as double, vat: json['vat']as double, total: json['total']as double, energy: json['energy']as int, ); } } - 方案二:保留
int类型,将字符串转为整数:
若factory Evsebill.fromJson(Map<String, dynamic> json) { return Evsebill( serial: int.parse(json['serial']), // 字符串转整数 value: json['value']as double, vat: json['vat']as double, total: json['total']as double, energy: json['energy']as int, ); }serial可能为空或非数字字符串,建议增加异常处理:int.tryParse(json['serial']) ?? 0
2. 正确获取并使用列表数据
可以通过状态管理或FutureBuilder来渲染列表,示例如下:
List<Evsebill>? _bills; @override void initState() { super.initState(); fetch().then((bills) { setState(() { _bills = bills; }); }); } @override Widget build(BuildContext context) { return _bills == null ? const CircularProgressIndicator() : ListView.builder( itemCount: _bills!.length, itemBuilder: (context, index) { final bill = _bills![index]; return ListTile( title: Text('单号: ${bill.serial}'), subtitle: Text('总金额: ${bill.total.toStringAsFixed(2)}'), ); }, ); }
3. 优化JSON解析(可选)
使用compute函数在单独的isolate中解析JSON,避免阻塞UI线程:
Future<List<Evsebill>> fetch() async { String? token = await this.storage.read(key: "token"); Map<String, String> headers = { "Content-Type": "application/json", "Accept": "application/json", "Authorization": "Bearer " + (token ?? ""), }; final response = await http.get(Uri.parse('${this.serverIP}:${this.serverPort}/user/contractedChargeTransactions?month=8&year=2022'), headers: headers); // 后台线程解析JSON return compute(parseBills, response.body); }
内容的提问来源于stack exchange,提问作者Bill Tertis
相关产品推荐
相关产品推荐

