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

Flutter请求服务器时遇FormatException错误与302状态码问题求助

Flutter请求服务器返回302错误及JSON解析异常排查

问题详情

向服务器发送数据时返回状态码302,同时触发未处理异常:

[ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: FormatException: Unexpected character (at character 1)
E/flutter ( 5424):  E/flutter ( 5424): ^ E/flutter (
5424): E/flutter ( 5424): #0 _ChunkedJsonParser.fail
(dart:convert-patch/convert_patch.dart:1383:5) E/flutter ( 5424): #1
_ChunkedJsonParser.parseNumber (dart:convert-patch/convert_patch.dart:1250:9) E/flutter ( 5424): #2
_ChunkedJsonParser.parse (dart:convert-patch/convert_patch.dart:915:22) E/flutter (5424): #3
_parseJson (dart:convert-patch/convert_patch.dart:35:10) E/flutter (5424): #4 JsonDecoder.convert (dart:convert/json.dart:612:36)
E/flutter (5424): #5 JsonCodec.decode (dart:convert/json.dart:216:41)
E/flutter ( 5424): #6 LoginCubit.auth
(package:muraba/features/presentation/login/cubit/login_cubit.dart:29:16)
E/flutter ( 5424):  E/flutter ( 5424): #7
LoginBody.build.
(package:muraba/features/presentation/login/login.dart:144:21)
E/flutter ( 5424):  E/flutter ( 5424):E/flutter (5424):

相关代码

请求逻辑代码

Future<void> auth(int number, String device_key)async {
  emit(LoginLoading());

  final response = await http.post(Uri.parse(ConfigUrl.sendMessage),
      body: jsonEncode(<String, dynamic>{
      "phone": number
      "device_key": device_key
  }));

  if(response.statusCode == 200) {
    final responseJson = json.decode(response.body) as Map<String, dynamic>;
    print(responseJson);
    emit(LoginLoaded(loginModel: LoginModel.fromJson(responseJson)));
  } else {
    print(response.statusCode);
    log(json.decode(response.body));
    emit(LoginError());
  }
}

按钮触发代码

Container(
  margin: EdgeInsets.fromLTRB(10, 0, 10, 20),
  child: InkWell(
    onTap: () async {
      final number = int.parse(_numberEditingController.text);
      const device_key = 'asdarwefvxcgczxcvvd';
      await context.read<LoginCubit>().auth(number, device_key);
      // context.go('/home');
    },
    child: Container(
      width: double.infinity
      color: Colors.green,
      padding: EdgeInsets.symmetric(vertical: 14),
      child: Text('Continue', style: TextStyle(fontSize: 19), textAlign: TextAlign.center,),
    ),
  ),
)

服务器响应截图

服务器响应截图

问题分析

  1. 请求参数语法错误:jsonEncode中的Map键值对之间缺少逗号("phone": number后未加逗号),导致生成的JSON格式非法,服务器无法正确解析请求。
  2. 302重定向未处理:状态码302表示请求需要重定向到其他地址,但http.post默认不自动跟随重定向,且重定向后的响应体通常不是JSON格式,直接调用json.decode会抛出FormatException。
  3. 异常处理缺失:else分支中直接解析响应体,未考虑非JSON格式的情况,导致未处理异常触发。
  4. 请求头缺失:未设置Content-Type: application/json,服务器可能无法识别请求体为JSON格式,进而返回异常响应。

修复方案

1. 修复请求逻辑代码

补充缺失的逗号、添加请求头并完善异常处理:

Future<void> auth(int number, String device_key) async {
  emit(LoginLoading());
  try {
    final response = await http.post(
      Uri.parse(ConfigUrl.sendMessage),
      headers: {'Content-Type': 'application/json'}, // 声明请求体格式
      body: jsonEncode(<String, dynamic>{
        "phone": number, // 添加缺失的逗号
        "device_key": device_key
      }),
    );

    if (response.statusCode == 200) {
      final responseJson = json.decode(response.body) as Map<String, dynamic>;
      print(responseJson);
      emit(LoginLoaded(loginModel: LoginModel.fromJson(responseJson)));
    } else if (response.statusCode == 302) {
      // 处理重定向逻辑,获取Location头地址
      final redirectUrl = response.headers['location'];
      if (redirectUrl != null) {
        print("重定向地址: $redirectUrl");
        // 可选:跟随重定向重新发起请求
        // final redirectResponse = await http.get(Uri.parse(redirectUrl));
      }
      emit(LoginError(message: "请求被重定向"));
    } else {
      print(response.statusCode);
      print("响应体内容: ${response.body}");
      emit(LoginError(message: "请求失败,状态码${response.statusCode}"));
    }
  } catch (e) {
    print("请求或解析异常: $e");
    emit(LoginError(message: "请求出错"));
  }
}

2. 修复按钮代码语法错误

在width: double.infinity后添加缺失的逗号:

Container(
  margin: EdgeInsets.fromLTRB(10, 0, 10, 20),
  child: InkWell(
    onTap: () async {
      final number = int.parse(_numberEditingController.text);
      const device_key = 'asdarwefvxcgczxcvvd';
      await context.read<LoginCubit>().auth(number, device_key);
      // context.go('/home');
    },
    child: Container(
      width: double.infinity, // 添加缺失的逗号
      color: Colors.green,
      padding: EdgeInsets.symmetric(vertical: 14),
      child: Text('Continue', style: TextStyle(fontSize: 19), textAlign: TextAlign.center,),
    ),
  ),
)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 00:25:19