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

Flutter应用启动及Google登录时出现FormatException错误求助

Flutter应用启动及Google登录时的JSON解析错误排查

问题现象

应用启动调用getNotificationList接口、Google登录调用registerUser接口时,均触发FormatException,错误日志显示尝试解析HTML内容而非预期的JSON:

E/flutter ( 5156): [ERROR:flutter/lib/ui/ui_dart_state.cc(198)] Unhandled Exception: FormatException: Unexpected character (at character 1)
E/flutter ( 5156): <!doctype html>
E/flutter ( 5156): ^
E/flutter ( 5156):
E/flutter ( 5156): #0      _ChunkedJsonParser.fail (dart:convert-patch/convert_patch.dart:1383:5)
E/flutter ( 5156): #1      _ChunkedJsonParser.parseNumber (dart:convert-patch/convert_patch.dart:1250:9)
E/flutter ( 5156): #2      _ChunkedJsonParser.parse (dart:convert-patch/convert_patch.dart:915:22)
E/flutter ( 5156): #3      _parseJson (dart:convert-patch/convert_patch.dart:35:10)
E/flutter ( 5156): #4      JsonDecoder.convert (dart:json.dart:612:36)

涉及的核心代码片段:

应用启动时的通知列表接口

Future<UserNotifications> getNotificationList(
    String start, String limit) async {
  client = http.Client();
  print(SessionManager.accessToken);
  final response = await client.post(
    Uri.parse(Const.getNotificationList),
    body: {
      Const.start: start,
      Const.limit: limit,
    },
    headers: {
      Const.uniqueKey: apiKey,
      Const.authorization: SessionManager.accessToken,
    },
  );
  print(response.body);
  final responseJson = jsonDecode(response.body);
  return UserNotifications.fromJson(responseJson);
}

Google登录时的用户注册接口

class ApiService {
    var client = http.Client();
    final apiKey = 'xxxx';

    Future<User> registerUser(HashMap<String, String> params) async {
      final response = await client.post(
        Uri.parse(Const.registerUser),
        body: params,
        headers: {Const.uniqueKey: apiKey},
      );
      final responseJson = jsonDecode(response.body);
      SessionManager sessionManager = SessionManager();
      await sessionManager.initPref();
      print(jsonEncode(User.fromJson(responseJson)));
      sessionManager.saveUser(jsonEncode(User.fromJson(responseJson)));
      return User.fromJson(responseJson);
    }
}

错误原因分析

从错误日志中的<!doctype html>可以明确:接口返回的是HTML错误页面,而非预期的JSON数据,常见触发原因包括:

  • 接口URL配置错误:Const.getNotificationList或Const.registerUser中的地址拼写错误、环境(开发/生产)混淆,导致请求到了不存在的页面(404错误)
  • 请求头参数无效:
    • 启动时SessionManager.accessToken未正确初始化或已过期,服务端返回401未授权的HTML错误页
    • apiKey与后端约定不一致,服务端拒绝请求并返回错误页面
  • 请求格式不符合要求:POST参数的编码方式、参数结构不符合后端接口定义,导致服务端无法处理返回错误页

解决方法

1. 验证接口URL正确性

检查Const类中配置的接口地址,确保和后端提供的完全一致,注意区分开发/生产环境的域名、路径拼写。

2. 校验请求头参数有效性

  • 启动调用getNotificationList前,确认SessionManager.accessToken已正确获取并初始化,避免空值或过期值;可在打印accessToken后增加非空判断
  • 核对apiKey是否与后端约定的完全一致,注意大小写、特殊字符是否正确

3. 先排查响应状态码及完整内容

在调用jsonDecode前,先打印HTTP响应状态码和完整返回体,根据状态码定位问题:

  • 404:接口地址错误
  • 401:Token无效或未授权
  • 400:请求参数错误
  • 5xx:服务端内部错误

4. 增加错误处理,避免崩溃

在代码中增加状态码判断和JSON解析异常捕获,防止非JSON返回导致应用崩溃,优化后的代码示例:

优化后的通知列表接口

Future<UserNotifications> getNotificationList(
    String start, String limit) async {
  client = http.Client();
  final accessToken = SessionManager.accessToken;
  print('Access Token: $accessToken');
  
  final response = await client.post(
    Uri.parse(Const.getNotificationList),
    body: {
      Const.start: start,
      Const.limit: limit,
    },
    headers: {
      Const.uniqueKey: apiKey,
      Const.authorization: accessToken ?? '',
    },
  );

  // 打印状态码和响应体,便于排查
  print('Notification API Status Code: ${response.statusCode}');
  print('Notification API Response: ${response.body}');

  // 先判断请求是否成功
  if (response.statusCode >= 200 && response.statusCode < 300) {
    try {
      final responseJson = jsonDecode(response.body);
      return UserNotifications.fromJson(responseJson);
    } catch (e) {
      throw Exception('JSON解析失败: $e');
    }
  } else {
    throw Exception('请求失败,状态码: ${response.statusCode},响应内容: ${response.body}');
  }
}

优化后的注册接口

class ApiService {
    var client = http.Client();
    final apiKey = 'xxxx';

    Future<User> registerUser(HashMap<String, String> params) async {
      final response = await client.post(
        Uri.parse(Const.registerUser),
        body: params,
        headers: {Const.uniqueKey: apiKey},
      );

      print('Register API Status Code: ${response.statusCode}');
      print('Register API Response: ${response.body}');

      if (response.statusCode >= 200 && response.statusCode < 300) {
        try {
          final responseJson = jsonDecode(response.body);
          final user = User.fromJson(responseJson);
          
          SessionManager sessionManager = SessionManager();
          await sessionManager.initPref();
          print(jsonEncode(user));
          sessionManager.saveUser(jsonEncode(user));
          
          return user;
        } catch (e) {
          throw Exception('用户信息JSON解析失败: $e');
        }
      } else {
        throw Exception('注册请求失败,状态码: ${response.statusCode},响应内容: ${response.body}');
      }
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 23:55:15