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

Flutter应用+Deno+MongoDB后端注册功能出现类型转换异常问题

解决Flutter注册时type 'Null' is not a subtype of type 'String'错误

这个错误的核心原因是你的Flutter前端代码期望后端返回特定字段,但Deno后端的注册接口返回的字段不匹配,导致前端解析时拿到null值,赋值给String类型变量时触发类型错误。

具体问题分析

看一下你的Flutter auth.dart里的_authenticate方法:

_token = responseData['idToken'];
_userId = responseData['localId'];
_expiryDate = DateTime.now().add(
  Duration(
    seconds: int.parse(
      responseData['expiresIn'],
    ),
  ),
);

这段代码默认后端会返回idToken、localId、expiresIn这三个字段,但你的Deno后端register接口返回的是:

ctx.response.body = { id: user.id, name: user.name, email: user.email };

完全没有前端需要的那三个字段,所以responseData['idToken']等调用返回的是null,而_token、_userId是String类型,赋值null就会抛出Null is not a subtype of String错误。

另外还有一个隐藏问题:你的前端错误处理依赖后端返回responseData['error']['message'],但后端当前的错误响应是{ message: "Email is already exist" },这也会导致前端解析错误时出现问题。

解决方案(推荐方案:调整后端匹配前端期望)

修改Deno的auth_controller.ts,调整返回格式,同时引入JWT生成认证token(生产环境建议用JWT库,比如djwt):

// 先安装djwt库:deno add djwt
import { createToken } from "https://deno.land/x/djwt@v3.0.1/mod.ts";

async register(ctx: RouterContext) {
  const { email, password } = await ctx.request.body().value;
  let user = await User.findOne({ email });
  if (user) {
    ctx.response.status = 422;
    // 调整错误格式匹配前端的HttpException解析逻辑
    ctx.response.body = { error: { message: "Email is already exist" } };
    return;
  }
  const hashedPassword = hashSync(password);
  user = new User({ email, password: hashedPassword });
  await user.save();

  // 生成JWT token,设置过期时间为1小时
  const secretKey = new TextEncoder().encode('your-strong-secret-key-here'); // 生产环境要使用环境变量存储密钥
  const payload = { 
    localId: user.id, 
    email: user.email,
    exp: Math.floor(Date.now() / 1000) + 3600 // 过期时间:当前时间+3600秒(1小时)
  };
  const idToken = await createToken({ alg: "HS256", typ: "JWT" }, payload, secretKey);

  // 返回前端需要的字段
  ctx.response.status = 201;
  ctx.response.body = { 
    idToken: idToken,
    localId: user.id,
    expiresIn: "3600", // 过期时间(秒)
    id: user.id, 
    name: user.name, 
    email: user.email 
  };
}

备选方案:调整前端适配后端当前格式

如果暂时不想修改后端,可以调整Flutter的_authenticate方法,适配现有后端返回:

Future<void> _authenticate(
  String email,
  String password,
  String urlSegment,
) async {
  final url = Uri.parse('http://10.0.2.2:8000/api/$urlSegment');
  try {
    final response = await http.post(
      url,
      body: json.encode(
        {
          'email': email,
          'password': password,
        },
      ),
    );
    final responseData = json.decode(response.body);
    
    // 适配后端的错误响应格式
    if (response.statusCode == 422) {
      throw HttpException(responseData['message']);
    }
    
    // 使用后端返回的id作为用户标识,自己设置过期时间
    _token = responseData['id']; // 生产环境建议还是用JWT,这里只是临时适配
    _userId = responseData['id'];
    _expiryDate = DateTime.now().add(
      Duration(hours: 1), // 自定义过期时间
    );
    
    _autoLogout();
    notifyListeners();
    final prefs = await SharedPreferences.getInstance();
    final userData = json.encode(
      {
        'token': _token,
        'userId': _userId,
        'expiryDate': _expiryDate!.toIso8601String(),
      },
    );
    prefs.setString('userData', userData);
  } catch (error) {
    throw error;
  }
}

验证步骤

  1. 重启Deno后端服务
  2. 重新运行Flutter应用
  3. 测试注册功能,应该不会再出现空值类型错误,同时错误提示也能正常显示

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 22:57:46