Flutter移动端调用Mock API获取用户数据不完整问题求助
问题现象
- Web端调用用户Mock API功能正常,但模拟器/实体手机上数据无法正常展示
- 通过
debugPrint查看,响应数据打印显示不完整,程序未抛出明显错误,但无法将数据转换为Users实例 - 调用结构更简单的Posts Mock API时运行完全正常
相关代码与输出
数据获取方法
Future<List<Users>> getUsers() async { try{ var response =await http.get(Uri.parse(baseUrl)); debugPrint("Get User Response"); debugPrint(response.body); debugPrint(response.statusCode.toString()); if(response.statusCode == 200){ var jsonData = jsonDecode(response.body); debugPrint("this is jsonData $jsonData"); final json_ = jsonData['users'] as List<dynamic>; List<Users> users = json_.map((e) => Users.fromMap(e)).toList(); debugPrint("this is users $users"); return users; } else{ return Future.error("Server Error"); } } catch(e){ return Future.error("Error Fetching Data"); } }
debugPrint输出
I/flutter (22977): Get User Response
I/flutter (22977): {"users":[{"id":1,"firstName":"Terry","lastName":"Medhurst","maidenName":"Smitham","age":50,"gender":"male","email":"atuny0@sohu.com","phone":"+63 791 675 8914","username":"atuny0","password":"9uQFF1Lh","birthDate":"2000-12-25","image":"https://robohash.org/hicveldicta.png","bloodGroup":"A−","height":189,"weight":75.4,"eyeColor":"Green","hair":{"color":"Black","type":"Strands"},"domain":"slashdot.org","ip":"117.29.86.254","address":{"address":"1745 T Street Southeast","city":"Washington","coordinates":{"lat":38.867033,"lng":-76.979235},"postalCode":"20020","state":"DC"},"macAddress":"13:69:BA:56:A3:74","university":"Capitol University","bank":{"cardExpire":"06/22","cardNumber":"50380955204220685","cardType":"maestro","currency":"Peso","iban":"NO17 0695 2754 967"},"company":{"address":{"address":"629 Debbie Drive","city":"Nashville","coordinates":{"lat":36.208114,"lng":-86.58621199999999},"postalCode":"37076","state":"TN"},"department":"Marketing","name":"Blanda-O'Keefe","title":"Help Desk Operator"},"ein":
I/flutter (22977): 200
I/flutter (22977): this is jsonData {users: [{id: 1, firstName: Terry, lastName: Medhurst, maidenName: Smitham, age: 50, gender: male, email: atuny0@sohu.com, phone: +63 791 675 8914, username: atuny0, password: 9uQFF1Lh, birthDate: 2000-12-25, image: https://robohash.org/hicveldicta.png, bloodGroup: A−, height: 189, weight: 75.4, eyeColor: Green, hair: {color: Black, type: Strands}, domain: slashdot.org, ip: 117.29.86.254, address: {address: 1745 T Street Southeast, city: Washington, coordinates: {lat: 38.867033, lng: -76.979235}, postalCode: 20020, state: DC}, macAddress: 13:69:BA:56:A3:74, university: Capitol University, bank: {cardExpire: 06/22, cardNumber: 50380955204220685, cardType: maestro, currency: Peso, iban: NO17 0695 2754 967}, company: {address: {address: 629 Debbie Drive, city: Nashville, coordinates: {lat: 36.208114, lng: -86.58621199999999}, postalCode: 37076, state: TN}, department: Marketing, name: Blanda-O'Keefe, title: Help Desk Operator}, ein: 20-9487066, ssn: 661-64-2976, userAgent: Mozilla/5.0 (Window
Users.fromMap方法
factory Users.fromMap(Map<String, dynamic> map) { return Users( id: map['id'] as int, firstName: map['firstName'] as String, lastName: map['lastName'] as String, maidenName: map['maidenName'] as String, age: map['age'] as int, gender: map['gender'] as String, email: map['email'] as String, phone: map['phone'] as String, username: map['username'] as String, password: map['password'] as String, birthDate: map['birthDate'] as String, image: map['image'] as String, bloodGroup: map['bloodGroup'] as String, height: map['height'] as num, weight: map['weight'] as double, eyeColor: map['eyeColor'] as String, hair: map['hair'] as Map, domain: map['domain'] as String, ip: map['ip'] as String, address: map['address'] as Map, macAddress: map['macAddress'] as String, university: map['university'] as String, bank: map['bank'] as Map, company: map['company'] as Map, ein: map['ein'] as String, ssn: map['ssn'] as String, userAgent: map['userAgent'] as String, ); }
API地址
- 用户API:https://dummyjson.com/users
- 帖子API:https://dummyjson.com/posts
问题原因及解决方案
核心原因
- debugPrint输出截断:Flutter的
debugPrint默认会限制输出长度,你看到的“数据不完整”只是打印被截断,实际response.body是完整的。 - 强制类型转换不安全:
fromMap中使用as强制转换,若字段类型不匹配(比如userAgent为null、weight返回int而非double),会导致转换失败,且被外层catch捕获后只返回通用错误,无法定位具体问题。
解决步骤
- 验证响应完整性:替换
debugPrint(response.body)为log(response.body)或写入临时文件,确认数据是否真的不完整。 - 修改fromMap为安全转换:使用空值合并运算符
??提供默认值,避免强制转换报错:
factory Users.fromMap(Map<String, dynamic> map) { return Users( id: map['id'] is int ? map['id'] : int.tryParse(map['id'].toString()) ?? 0, firstName: map['firstName'] as String? ?? '', lastName: map['lastName'] as String? ?? '', maidenName: map['maidenName'] as String? ?? '', age: map['age'] is int ? map['age'] : int.tryParse(map['age'].toString()) ?? 0, gender: map['gender'] as String? ?? '', email: map['email'] as String? ?? '', phone: map['phone'] as String? ?? '', username: map['username'] as String? ?? '', password: map['password'] as String? ?? '', birthDate: map['birthDate'] as String? ?? '', image: map['image'] as String? ?? '', bloodGroup: map['bloodGroup'] as String? ?? '', height: map['height'] is num ? map['height'] : num.tryParse(map['height'].toString()) ?? 0, weight: map['weight'] is double ? map['weight'] : double.tryParse(map['weight'].toString()) ?? 0.0, eyeColor: map['eyeColor'] as String? ?? '', hair: map['hair'] as Map<String, dynamic>? ?? {}, domain: map['domain'] as String? ?? '', ip: map['ip'] as String? ?? '', address: map['address'] as Map<String, dynamic>? ?? {}, macAddress: map['macAddress'] as String? ?? '', university: map['university'] as String? ?? '', bank: map['bank'] as Map<String, dynamic>? ?? {}, company: map['company'] as Map<String, dynamic>? ?? {}, ein: map['ein'] as String? ?? '', ssn: map['ssn'] as String? ?? '', userAgent: map['userAgent'] as String? ?? '', ); }
- 捕获具体转换错误:在遍历转换时添加局部try-catch,定位具体出错的字段:
List<Users> users = []; for (var e in json_) { try { users.add(Users.fromMap(e)); } catch (e, stackTrace) { debugPrint("转换用户数据失败: $e"); debugPrint(stackTrace.toString()); } }
- 检查移动端网络配置:确认设备无代理、防火墙限制,能正常访问用户API。
内容的提问来源于stack exchange,提问作者A_ N_

