Flutter Retrofit中DateTime参数的ISO 8061序列化实现方案
解决Flutter Retrofit中DateTime参数序列化为ISO 8601格式的问题
我来帮你搞定这个DateTime参数的序列化需求,结合flutter_retrofit(基于Dio)的特性,有两种非常实用的方案,我给你详细拆解下:
方案一:自定义参数转换器(推荐,精准控制)
flutter_retrofit支持为单个Query参数指定自定义转换器,专门处理DateTime到ISO 8601字符串的转换,这是最贴合需求的方式。
步骤1:实现DateTime转换器
创建一个类实现Converter<DateTime, String>接口,负责把DateTime转成标准的ISO 8601格式字符串:
import 'package:retrofit/retrofit.dart'; class DateTimeConverter implements Converter<DateTime, String> { @override String convert(DateTime value) { // 直接调用DateTime的toIso8601String()方法即可生成目标格式 return value.toIso8601String(); } }
步骤2:在Retrofit接口中使用转换器
注意:你原来的@Headers中写动态authKey是行不通的——@Headers注解的内容是编译时固定的,不能引用变量。所以要把Authorization改为动态的@Header参数传递。修改后的接口如下:
import 'package:dio/dio.dart'; import 'package:retrofit/retrofit.dart'; @RestApi(baseUrl: "https://address.com") abstract class UserApi { factory UserApi(Dio dio, {String baseUrl}) = _UserApi; @GET("/users") @Headers({ "Accept": "application/json", }) Future<List<User>> getUsers( // 为每个DateTime参数指定自定义转换器 @Query("fromDate", converter: DateTimeConverter()) DateTime from, @Query("toDate", converter: DateTimeConverter()) DateTime to, // 动态传递Authorization头部 @Header("Authorization") String authorization, ); }
步骤3:生成并调用接口
修改完接口后,重新运行Retrofit的代码生成命令:
flutter pub run build_runner build --delete-conflicting-outputs
调用时传入动态的Authorization值:
final dio = Dio(); final userApi = UserApi(dio); // 构造认证字符串 final authKey = "your_base64_encoded_auth_string"; final authorizationHeader = "Basic $authKey"; // 调用接口 final users = await userApi.getUsers( DateTime(2021, 2, 21, 12), DateTime(2021, 2, 27, 12), authorizationHeader, );
方案二:全局Dio拦截器(批量处理)
如果你希望所有DateTime类型的Query参数都自动转成ISO 8601格式,可以用Dio的拦截器统一处理,不用逐个参数加转换器。
步骤1:实现DateTime拦截器
创建一个拦截器,在请求发送前遍历所有Query参数,把DateTime类型的值转成目标字符串:
import 'package:dio/dio.dart'; class DateTimeQueryInterceptor extends Interceptor { @override void onRequest(RequestOptions options, RequestInterceptorHandler handler) { // 遍历并处理所有Query参数 options.queryParameters.forEach((key, value) { if (value is DateTime) { options.queryParameters[key] = value.toIso8601String(); } }); super.onRequest(options, handler); } }
步骤2:为Dio添加拦截器
创建Dio实例时添加这个拦截器,之后所有通过该Dio实例发起的请求都会自动处理DateTime参数:
final dio = Dio(); // 添加全局拦截器 dio.interceptors.add(DateTimeQueryInterceptor()); final userApi = UserApi(dio); // 调用接口时无需额外处理DateTime参数 final users = await userApi.getUsers( DateTime(2021, 2, 21, 12), DateTime(2021, 2, 27, 12), "Basic $authKey", );
两种方案对比
- 自定义转换器:精准控制单个参数的转换逻辑,适合只需要处理特定参数的场景,代码可读性更强。
- 全局拦截器:一次性处理所有DateTime类型的Query参数,适合项目中有大量DateTime参数需要统一转换的场景。
内容的提问来源于stack exchange,提问作者kosiara - Bartosz Kosarzycki
相关产品推荐
相关产品推荐

