You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 03:03:22