Flutter登录API调用报错:'String'不是'Map<dynamic, dynamic>'子类型求助
解决Flutter登录API调用中的
type 'String' is not a subtype of type 'Map<dynamic, dynamic>'错误 这个错误的核心原因是你直接将response.data赋值给了Map类型变量,但实际上response.data是字符串类型——可能是Dio没有自动解析JSON响应,或者服务器返回的响应格式不符合预期。
以下是两种可行的解决方法:
方法一:手动判断并解析响应数据
导入dart:convert包,在处理响应前先判断数据类型,字符串类型的话就用jsonDecode解析为Map:
import 'package:dio/dio.dart'; import 'package:flutter/material.dart'; import 'dart:convert'; // 新增导入 class AuthService { static String? token; Future<bool> login({ required String email, required String password, }) async { try { var response = await Dio().post( "http://my-api/index/login", options: Options( headers: { "Content-Type": "application/json", }, ), data: { "email": email, "password": password, }, ); if (response.statusCode == 200) { Map<String, dynamic> obj; // 判断数据类型并处理 if (response.data is String) { obj = jsonDecode(response.data) as Map<String, dynamic>; } else { obj = response.data as Map<String, dynamic>; } token = obj["data"]["token"]; return true; } else { throw Exception('登录失败'); } } on DioException catch (e) { if (e.response?.statusCode == 401) { String errorMsg = "账号或密码错误"; // 统一处理错误响应的解析 if (e.response?.data is String) { final errorData = jsonDecode(e.response!.data) as Map<String, dynamic>; errorMsg = errorData["message"] ?? errorMsg; } else if (e.response?.data is Map) { errorMsg = e.response!.data["message"] ?? errorMsg; } debugPrint('Error 401: $errorMsg'); throw Exception(errorMsg); } else { debugPrint('错误详情: ${e.toString()}'); throw Exception('登录失败'); } } } }
方法二:配置Dio强制自动解析JSON
创建全局Dio实例并设置responseType: ResponseType.json,确保Dio自动将JSON响应转换为Map,无需手动解析:
// 全局Dio配置 final Dio dio = Dio(BaseOptions( responseType: ResponseType.json, headers: { "Content-Type": "application/json", }, )); class AuthService { static String? token; Future<bool> login({ required String email, required String password, }) async { try { var response = await dio.post( // 使用全局配置的dio实例 "http://my-api/index/login", data: { "email": email, "password": password, }, ); if (response.statusCode == 200) { final obj = response.data as Map<String, dynamic>; token = obj["data"]["token"]; return true; } else { throw Exception('登录失败'); } } on DioException catch (e) { if (e.response?.statusCode == 401) { String errorMsg = "账号或密码错误"; if (e.response?.data is Map) { errorMsg = e.response!.data["message"] ?? errorMsg; } debugPrint('Error 401: $errorMsg'); throw Exception(errorMsg); } else { debugPrint('错误详情: ${e.toString()}'); throw Exception('登录失败'); } } } }
另外建议使用Map<String, dynamic>替代泛型Map,提升代码的类型安全性,减少潜在的类型错误。
内容的提问来源于stack exchange,提问作者Dzy
相关产品推荐
相关产品推荐

