为什么Flutter中Dio接收的JSON响应有时无法自动反序列化
问题原因分析
Dio 默认自动将响应反序列化为 _InternalLinkedHashMap 的前提有两个:
- 响应头的
Content-Type字段值包含application/json - Dio 实例配置的
responseType为默认的ResponseType.json
你遇到的反序列化行为不一致问题,根源是你用 Rust 编写的接口直接返回序列化后的 JSON 字符串,web 框架默认会给该响应设置 Content-Type: text/plain,Dio 识别到非 JSON 类型的响应头就不会自动反序列化;其他返回了正确 Content-Type 的接口则可以正常转 Map,就出现了时好时坏的情况。
解决方案
方案1:服务端修复(最推荐)
不要在 Rust 接口中手动将响应序列化为 String 返回,直接用框架自带的 JSON 响应构造方法,会自动添加正确的 application/json 响应头。你当前用的是 actix-web 框架,代码修改如下:
#[get("/v1/playlist")] pub fn user_playlist() -> impl Responder { use schema::playlist::dsl::*; let connection = config::establish_connection(); let results = playlist.filter(creator.eq(1)) .limit(1) .load::<QueryPlaylist>(&connection) .expect("Error loading posts"); let res = ApiResponse { body: results, ..Default::default() }; // 直接返回json响应,框架自动加Content-Type: application/json HttpResponse::Ok().json(res) }
方案2:Dio端全局强制反序列化
如果无法修改服务端代码,可以在Dio端做配置,强制所有响应走JSON反序列化:
方法A:自定义响应转换器
重写Dio的转换器逻辑,忽略响应头的Content-Type判断,强制按JSON解析:
import 'package:dio/dio.dart'; class ForceJsonTransformer extends BackgroundTransformer { @override Future<dynamic> transformResponse(RequestOptions options, ResponseBody responseBody) async { // 强制指定响应类型为JSON options.responseType = ResponseType.json; // 伪造JSON响应头,触发默认解析逻辑 options.headers[Headers.contentTypeHeader] = Headers.jsonContentType; return super.transformResponse(options, responseBody); } } // 初始化Dio的时候绑定转换器 final dio = Dio(); dio.transformer = ForceJsonTransformer();
方法B:在拦截器中手动转换
在现有的响应拦截器中增加判断,字符串类型的响应手动转JSON:
import 'dart:convert'; @override Future onResponse(Response response, ResponseInterceptorHandler handler) async { // 手动反序列化字符串类型的JSON响应 if (response.data is String) { try { response.data = jsonDecode(response.data as String); } catch (_) { // 非合法JSON响应保留原内容即可 } } Response handleResponse = await autoLogin(response); Response handleAccessToken = await handleResponseByCode(handleResponse); return super.onResponse(handleAccessToken, handler); }
内容的提问来源于stack exchange,提问作者Dolphin
相关产品推荐
相关产品推荐

