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

Dio请求遇FormatException错误,Postman正常请求求排查方案

问题:Dio请求抛出FormatException异常,Postman请求正常

使用Dio发起网络请求时遇到以下错误:

DioError [DioErrorType.other]: FormatException: Unexpected character (at line 9, character 1)

已确认Postman发送相同参数可正常获取响应,但修改Model的JSON解析方式后问题仍未解决,需分析原因并给出解决方案。

相关代码实现

DioHelper类

class DioHelper {
  static late Dio dio;
  static init() {
    dio = Dio(BaseOptions(
      baseUrl: "https://management.rawcodev.com/api/",
      receiveDataWhenStatusError: true,
      // 避免抛出Http status error 422这类响应错误
      validateStatus: (status) => true,
    ));
  }

  static Future<Response> getData({
    required String path,
    Map<String, dynamic>? query,
    String lang = "en",
    String? token,
  }) async {
    dio.options.headers = {
      "lang": lang,
      "Authorization": token,
      "Content-Type": "application/json"
    };
    return await dio.get(path, queryParameters: query);
  }
}

Cubit中获取数据的方法

Attendance_History_Model? attendHistoryModel;
void getAttendHistory() {
  emit(AttendanceHistoryLoding());
  DioHelper.getData(path: AttendHistory, query: {
    "mod": "attendance-history",
    "key": "ABC@123",
    "user_id": user_idconst,
    "device_id": "device-1"
  }).then((value) {
    if (value.statusCode == 200) {
      attendHistoryModel = Attendance_History_Model.fromJson(value.data);
      emit(AttendanceHistorySuccess());
    } else {
      print("error");
      print(value.statusCode);
    }
  }).catchError((error) {
    print(error.toString());
    emit(AttendanceHistoryError());
  });
}

问题原因分析

  1. JSON解析失败:FormatException本质是Dio尝试自动将响应解析为JSON时失败,可能是响应内容并非标准JSON格式(比如包含隐藏字符、HTML错误页面、编码不匹配)。
  2. Content-Type不匹配:若服务器返回的Content-Type响应头不是application/json,Dio的自动JSON解析逻辑会出错,而Postman会自动识别响应格式并处理。
  3. 响应编码问题:服务器返回的响应编码不是UTF-8(比如GBK),Dio默认用UTF-8解析会导致字符解析异常。
  4. 异常响应未被捕获:由于validateStatus: (status) => true,所有状态码的响应都会被返回,若服务器在非200状态下返回非JSON内容(如HTML错误页),也会触发解析错误。

解决方案

1. 先排查原始响应内容

在Cubit的请求回调中打印原始响应内容,确认是否为合法JSON:

DioHelper.getData(...).then((value) {
  // 打印原始响应字符串,检查是否有异常字符或非JSON内容
  print("原始响应内容: ${value.data}");
  print("响应头Content-Type: ${value.headers['content-type']}");
  
  if (value.statusCode == 200) {
    try {
      // 手动解析JSON并捕获异常
      var jsonData = jsonDecode(value.data);
      attendHistoryModel = Attendance_History_Model.fromJson(jsonData);
      emit(AttendanceHistorySuccess());
    } catch (e) {
      print("Model解析失败: $e");
    }
  } else {
    print("请求状态码异常: ${value.statusCode}");
  }
})

2. 关闭Dio自动JSON解析,手动处理

修改Dio配置,将响应类型设为原始字符串,再手动解析JSON,避免自动解析失败抛出异常:

static Future<Response> getData({
  required String path,
  Map<String, dynamic>? query,
  String lang = "en",
  String? token,
}) async {
  dio.options.headers = {
    "lang": lang,
    "Authorization": token,
    "Content-Type": "application/json"
  };
  // 设置响应类型为原始字符串,关闭自动JSON解析
  dio.options.responseType = ResponseType.plain;
  
  Response response = await dio.get(path, queryParameters: query);
  
  // 手动尝试解析JSON
  try {
    response.data = jsonDecode(response.data);
  } catch (e) {
    print("JSON解析失败: $e");
    print("原始响应内容: ${response.data}");
  }
  
  return response;
}

3. 处理响应编码问题

若服务器返回非UTF-8编码的响应,可自定义响应解码器(需引入charset_converter包处理非UTF-8编码):

static init() {
  dio = Dio(BaseOptions(
    baseUrl: "https://management.rawcodev.com/api/",
    receiveDataWhenStatusError: true,
    validateStatus: (status) => true,
    // 自定义解码器,处理GBK编码示例
    responseDecoder: (List<int> bytes, RequestOptions options, ResponseBody responseBody) {
      String data = gbk.decode(bytes); // 若为GBK编码
      return jsonDecode(data);
    },
  ));
}

4. 过滤异常响应

即使设置了validateStatus: true,也可在回调中先判断响应是否为JSON格式,再进行解析:

if (value.statusCode == 200) {
  // 先判断响应是否为JSON格式
  if (value.headers['content-type']?.contains('application/json') == true) {
    try {
      attendHistoryModel = Attendance_History_Model.fromJson(value.data);
      emit(AttendanceHistorySuccess());
    } catch (e) {
      print("Model解析失败: $e");
    }
  } else {
    print("响应非JSON格式: ${value.headers['content-type']}");
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 04:23:16