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
相关产品推荐
相关产品推荐

