Flutter调用Restful API报错:期望Map<String,dynamic>却得到String
问题分析与解决方案
问题1:判断response.statusCode==201时抛出异常"OK,200"且无数据
- 原因:你的API实际返回的HTTP状态码是200(正常响应),但代码里错误判断了201(资源创建成功状态码),因此进入异常分支;同时该分支未处理200状态的响应数据,导致显示"无数据"。
问题2:判断response.statusCode==200时报类型错误
- 原因:API返回的是List<Map<String,dynamic>>(数组包裹的对象),但代码里直接尝试将响应体解析成
Map<String,dynamic>,类型不匹配引发报错。
改进代码示例
1. LoginModel 定义
class LoginModel { final String accessToken; final String ipAddress; final String passwordHash; LoginModel({ required this.accessToken, required this.ipAddress, required this.passwordHash, }); // 从Map转换为LoginModel实例 factory LoginModel.fromMap(Map<String, dynamic> map) { return LoginModel( accessToken: map['access_token'] ?? '', ipAddress: map['ip_address'] ?? '', passwordHash: map['password_hash'] ?? '', ); } }
2. 修正后的请求代码
import 'dart:convert'; import 'package:http/http.dart' as http; Future<LoginModel?> login(String account, String password) async { final url = Uri.parse('你的API登录接口地址'); final headers = {'Content-Type': 'application/json'}; final body = jsonEncode({ 'account': account, 'password': password, }); try { final response = await http.post(url, headers: headers, body: body); // 匹配API实际返回的200状态码 if (response.statusCode == 200) { // 先解析为List,再取第一个元素转成Map final List<dynamic> responseList = jsonDecode(response.body); if (responseList.isNotEmpty) { return LoginModel.fromMap(responseList[0] as Map<String, dynamic>); } return null; } else { // 处理登录失败的异常状态,比如401账号密码错误等 throw Exception('登录失败,状态码:${response.statusCode}'); } } catch (e) { throw Exception('请求异常:$e'); } }
额外注意事项
- 确认API返回的
Content-Type是否为application/json,否则jsonDecode会解析失败。 - 保留数组非空判断,避免API返回空数组时出现索引越界问题。
- 实际开发中可封装统一的网络请求工具类,减少重复代码。
内容的提问来源于stack exchange,提问作者Chavon
相关产品推荐
相关产品推荐

