Flutter Retrofit单API返回两种不同JSON响应的类型转换问题
解决Retrofit多结构JSON响应解析问题
针对同一个API返回两种不同JSON结构,且解析时出现类型转换错误的问题,给你两种实用的解决思路:
方案一:用密封类+统一实体类(推荐)
这种方式类型安全,能避免后续维护时的类型错误。核心思路是利用两个响应的共同字段(count、type、data)定义统一响应类,再用密封类区分不同的data结构:
首先定义密封类区分不同的data类型:
sealed class ApiData {} // 对应响应1的认证数据 class AuthData extends ApiData { final String tokenType; final int expiresIn; final String accessToken; final String refreshToken; final int userId; AuthData({ required this.tokenType, required this.expiresIn, required this.accessToken, required this.refreshToken, required this.userId, }); factory AuthData.fromJson(Map<String, dynamic> json) { return AuthData( tokenType: json['token_type'], expiresIn: json['expires_in'], accessToken: json['access_token'], refreshToken: json['refresh_token'], userId: json['userId'], ); } } // 对应响应2的OTP数据 class OtpData extends ApiData { final bool success; final bool otpEnabled; final String message; final String timestamp; final int otp; OtpData({ required this.success, required this.otpEnabled, required this.message, required this.timestamp, required this.otp, }); factory OtpData.fromJson(Map<String, dynamic> json) { return OtpData( success: json['success'], otpEnabled: json['otpEnabled'], message: json['message'], timestamp: json['timestamp'], otp: json['otp'], ); } }
然后定义统一的响应实体,根据type字段判断解析哪种data:
class ApiResponse { final int count; final String type; final ApiData data; ApiResponse({ required this.count, required this.type, required this.data, }); factory ApiResponse.fromJson(Map<String, dynamic> json) { final String responseType = json['type']; final dataJson = json['data']; late ApiData data; if (responseType == 'object') { data = AuthData.fromJson(dataJson); } else if (responseType == 'success') { data = OtpData.fromJson(dataJson); } else { throw Exception('未知响应类型: $responseType'); } return ApiResponse( count: json['count'], type: responseType, data: data, ); } }
之后在Retrofit接口中直接返回ApiResponse即可:
@GET("your-api-path") Future<ApiResponse> fetchResponse();
方案二:动态解析+类型判断(快速临时方案)
如果不想定义实体类,可以直接用Map<String, dynamic>作为响应类型,然后在处理响应时根据type字段分支处理,注意手动判断字段类型:
// Retrofit接口定义 @GET("your-api-path") Future<Map<String, dynamic>> fetchResponse(); // 处理响应的逻辑 void handleApiResponse(Map<String, dynamic> response) { final String type = response['type']; final data = response['data']; if (type == 'object') { // 处理认证数据,直接取值并确保类型正确 String accessToken = data['access_token'] as String; int userId = data['userId'] as int; // ...后续业务逻辑 } else if (type == 'success') { // 处理OTP数据 int otp = data['otp'] as int; String message = data['message'] as String; // ...后续业务逻辑 } }
为什么之前的方法会报错?
- 使用
Map<String, String>时,因为响应中存在int类型的字段(比如expires_in、userId、otp),强制转换为String会触发type 'int' is not a subtype of type 'String'错误。 - 使用
Map<String, dynamic>生成文件报错,大概率是Retrofit代码生成器(比如retrofit_generator)对动态类型的支持问题,或者没有正确配置序列化依赖(比如json_serializable)。
内容的提问来源于stack exchange,提问作者Farhana Naaz Ansari
相关产品推荐
相关产品推荐

