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

Flutter iOS认证功能报错:_Map<String,dynamic>无法转为String

Flutter iOS认证功能sendOtp报错问题

问题概述

在Flutter开发的iOS应用中实现认证功能,登录页验证凭据后调用sendOtp方法时出现类型转换错误,导致认证完成后主页面无法正常跳转。

相关代码

User类实现

class User {
  final String fullname;
  final String username;
  final String email;
  final String password;
  final String token;
  final String type;
  final String id;
  final String pin;
  final bool isVerified;
  
  User({
    required this.fullname,
    required this.username,
    required this.email,
    required this.password,
    required this.token,
    required this.type,
    required this.id,
    required this.pin,
    required this.isVerified,
  });

  Map<String, dynamic> toMap() {
    return {
      'fullname': fullname,
      'username': username,
      'email': email,
      'password': password,
      'token': token,
      'type': type,
      'id': id,
      'pin': pin,
      'isVerified': isVerified,
    };
  }

  factory User.fromMap(Map<String, dynamic> map) {
    return User(
      fullname: map['fullname'] ?? '',
      username: map['username'] ?? '',
      email: map['email'] ?? '',
      password: map['password'] ?? '',
      token: map['token'] ?? '',
      type: map['type'] ?? '',
      id: map['_id'] ?? '',
      pin: map['pin'] ?? '',
      isVerified: map['isVerified'] ?? false,
    );
  }

  String toJson() => json.encode(toMap());

  factory User.fromJson(String source) => User.fromMap(json.decode(source));
}

sendOtp方法实现

void sendOtp({
  required BuildContext context,
  required String email,
  required String sendPurpose,
  required VoidCallback onTapDialogButton,
}) async {
  try {
    showDialogLoader(context);

    http.Response res = await http
        .post(Uri.parse("$uri/api/sendOtp/$sendPurpose"),
            headers: <String, String>{
              "Content-Type": "application/json; charset=UTF-8",
            },
            body: jsonEncode({
              "email": email,
            }))
        .timeout(const Duration(seconds: 25));
    Navigator.of(context, rootNavigator: true).pop('dialog');
    print(res.statusCode);
    statusCodeHandler(
      context: context,
      response: res,
      onSuccess: () {
        showAlertMessage(
          context: context,
          title: "Verify Account",
          message: "Please Check Mail For OTP Code",
          onTap: onTapDialogButton,
        );
      },
    );
  } on TimeoutException catch (e) {
    showTimeOutError(
      context: context,
      popDialogAndLoader: true,
    );
  } on SocketException catch (e) {
    showNoInternetError(
      context: context,
      popDialogAndLoader: true,
    );
  } on Error catch (e) {
    print('Send Otp Error: $e');
  }
}

报错信息

Send Otp Error: type '_Map<String, dynamic>' is not a subtype of type 'String'

解决方案

错误原因分析

该错误是由于代码中将Map<String, dynamic>类型的数据错误地当作String类型处理导致的,大概率出现在statusCodeHandler函数中处理HTTP响应体的逻辑里——当接口返回JSON格式的错误信息时,直接将响应体当作String使用,而没有先解析成Map。

具体修复步骤

  1. 修正statusCodeHandler的响应处理逻辑
    确保在处理非200状态码的响应时,先解析响应体为Map,再提取错误信息:

    void statusCodeHandler({
      required BuildContext context,
      required http.Response response,
      required VoidCallback onSuccess,
    }) {
      if (response.statusCode == 200) {
        onSuccess();
      } else {
        try {
          // 解析响应体为Map
          Map<String, dynamic> errorData = jsonDecode(response.body);
          String errorMessage = errorData['message'] ?? '未知错误';
          showAlertMessage(
            context: context,
            title: '错误',
            message: errorMessage,
          );
        } catch (e) {
          // 解析失败时直接使用原始响应体
          showAlertMessage(
            context: context,
            title: '错误',
            message: response.body,
          );
        }
      }
    }
    
  2. 补充错误捕获场景
    在sendOtp的错误捕获中添加对FormatException的处理,覆盖JSON解析失败的场景:

    } on FormatException catch (e) {
      print('JSON解析错误: $e');
      showAlertMessage(
        context: context,
        title: '错误',
        message: '数据解析失败',
      );
    }
    
  3. 检查用户信息解析逻辑
    确认登录后解析用户信息时,是否正确调用对应方法:如果是从接口直接获取Map数据,使用User.fromMap;如果是JSON字符串,使用User.fromJson,避免类型不匹配。

  4. 验证页面跳转逻辑
    检查onTapDialogButton回调中的页面跳转代码,确保用户状态已正确保存,跳转条件没有被错误拦截。

内容的提问来源于stack exchange,提问作者Diana

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 09:26:13