Retrofit 2.0技术问询:如何映射不同类型的对象?
我来帮你搞定Retrofit 2.0里不同类型对象的映射问题,结合你给出的JSON响应结构,咱们一步步实现:
步骤1:定义匹配JSON结构的实体类
首先得把JSON里的每一层都转换成对应的Java实体类,注意用@SerializedName处理JSON下划线命名和Java驼峰命名的差异:
最外层响应实体
这个类包裹了success状态和details数据,用泛型来兼容不同类型的details内容:
import com.google.gson.annotations.SerializedName; public class ApiResponse<T> { private boolean success; private T details; // Getter & Setter public boolean isSuccess() { return success; } public void setSuccess(boolean success) { this.success = success; } public T getDetails() { return details; } public void setDetails(T details) { this.details = details; } }
Details实体(包含多类型数据)
对应JSON里的details对象,里面包含banners数组和recent_books(这里假设recent_books也是数组,你可以根据实际结构调整字段类型):
import java.util.List; public class Details { private List<Banner> banners; private List<RecentBook> recent_books; // Getter & Setter public List<Banner> getBanners() { return banners; } public void setBanners(List<Banner> banners) { this.banners = banners; } public List<RecentBook> getRecentBooks() { return recent_books; } public void setRecentBooks(List<RecentBook> recent_books) { this.recent_books = recent_books; } }
Banner实体
对应banners数组里的单个对象:
import com.google.gson.annotations.SerializedName; public class Banner { @SerializedName("banner_id") private String bannerId; @SerializedName("file_id") private String fileId; private String title; private String description; private String created; private String modified; private String deleted; @SerializedName("file_name") private String fileName; @SerializedName("orig_file_name") private String origFileName; // 所有字段的Getter & Setter,这里省略部分示例 public String getBannerId() { return bannerId; } public void setBannerId(String bannerId) { this.bannerId = bannerId; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } }
RecentBook实体
根据recent_books的实际JSON结构定义字段,示例如下:
import com.google.gson.annotations.SerializedName; public class RecentBook { @SerializedName("book_id") private String bookId; private String title; private String author; // 其他字段... // Getter & Setter public String getBookId() { return bookId; } public void setBookId(String bookId) { this.bookId = bookId; } }
步骤2:定义Retrofit接口
创建接口描述API请求,指定返回的泛型类型:
import retrofit2.Call; import retrofit2.http.GET; public interface ApiService { // 替换成你的实际API端点路径 @GET("home-data") Call<ApiResponse<Details>> getHomeData(); }
步骤3:初始化Retrofit并发起请求
首先确保项目添加了Retrofit和Gson转换器的依赖(以Gradle为例):
implementation 'com.squareup.retrofit2:retrofit:2.9.0' implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
然后初始化Retrofit并调用接口:
import retrofit2.Call; import retrofit2.Callback; import retrofit2.Response; import retrofit2.Retrofit; import retrofit2.converter.gson.GsonConverterFactory; import com.google.gson.Gson; import com.google.gson.GsonBuilder; public class RetrofitClient { private static final String BASE_URL = "https://your-base-url.com/"; // 替换成你的基础URL public static void fetchHomeData() { Gson gson = new GsonBuilder() .setLenient() // 可选,处理格式不严格的JSON .create(); Retrofit retrofit = new Retrofit.Builder() .baseUrl(BASE_URL) .addConverterFactory(GsonConverterFactory.create(gson)) .build(); ApiService apiService = retrofit.create(ApiService.class); Call<ApiResponse<Details>> call = apiService.getHomeData(); call.enqueue(new Callback<ApiResponse<Details>>() { @Override public void onResponse(Call<ApiResponse<Details>> call, Response<ApiResponse<Details>> response) { if (response.isSuccessful() && response.body() != null) { ApiResponse<Details> apiResponse = response.body(); if (apiResponse.isSuccess()) { // 获取不同类型的数据 List<Banner> banners = apiResponse.getDetails().getBanners(); List<RecentBook> recentBooks = apiResponse.getDetails().getRecentBooks(); // 在这里处理数据,比如展示到UI上 } else { // 处理业务逻辑失败的情况(比如success为false) } } else { // 处理HTTP请求失败的情况 } } @Override public void onFailure(Call<ApiResponse<Details>> call, Throwable t) { // 处理网络错误 t.printStackTrace(); } }); } }
特殊场景:动态类型的Details
如果API中details字段可能返回不同类型的对象(比如有时候是Banner列表,有时候是RecentBook列表),可以利用Retrofit的泛型特性灵活处理:
定义通用接口方法:
@GET("dynamic-data") <T> Call<ApiResponse<T>> getDynamicData();
调用时指定具体类型:
// 当details是Banner列表时 Call<ApiResponse<List<Banner>>> bannerCall = apiService.getDynamicData(); // 当details是RecentBook列表时 Call<ApiResponse<List<RecentBook>>> bookCall = apiService.getDynamicData();
这样就能轻松处理不同类型的对象映射啦!
内容的提问来源于stack exchange,提问作者Dale Julian
相关产品推荐
相关产品推荐

