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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 09:42:34