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

如何使用Retrofit解析包含不同大小对象与数组的JSON对象?

解决Retrofit解析含不同属性对象的JSON数组问题

嘿,我看你在纠结用Retrofit解析那种混着不同属性对象的JSON数组对吧?我之前也踩过这个坑,给你分享几个亲测好用的解法:

1. 自定义Gson TypeAdapter(灵活适配复杂场景)

如果你的JSON数组里的对象差异比较大,比如有的是文章、有的是视频,结构完全不一样,自定义TypeAdapter是最灵活的方案。

先举个典型的JSON示例:

[
{"type": "article", "title": "Retrofit实战技巧", "content": "详细解析Retrofit的各种用法..."},
{"type": "video", "title": "Gson多态解析教程", "duration": 180}
]

第一步:定义基类和子类

先抽取出所有对象的公共字段作为基类,再分别定义不同类型的子类:

// 基类,存放公共字段
public abstract class BaseItem {
    public String type;
}

// 文章类型的子类
public class ArticleItem extends BaseItem {
    public String title;
    public String content;
}

// 视频类型的子类
public class VideoItem extends BaseItem {
    public String title;
    public int duration;
}

第二步:编写自定义TypeAdapter

这个Adapter的作用就是根据type字段判断对象类型,然后解析成对应的子类:

public class ItemTypeAdapter extends TypeAdapter<BaseItem> {
    private final Gson gson = new Gson();

    @Override
    public void write(JsonWriter out, BaseItem value) throws IOException {
        // 序列化的时候直接用对应子类的类型解析
        gson.toJson(value, value.getClass(), out);
    }

    @Override
    public BaseItem read(JsonReader in) throws IOException {
        // 先把JSON读成JsonObject,拿到type字段
        JsonObject jsonObject = JsonParser.parseReader(in).getAsJsonObject();
        String itemType = jsonObject.get("type").getAsString();
        
        // 根据type字段解析成对应的子类
        switch (itemType) {
            case "article":
                return gson.fromJson(jsonObject, ArticleItem.class);
            case "video":
                return gson.fromJson(jsonObject, VideoItem.class);
            default:
                throw new IllegalArgumentException("遇到未知的对象类型:" + itemType);
        }
    }
}

第三步:给Retrofit配置自定义Gson

把这个TypeAdapter注册到Gson里,再传给Retrofit的转换器:

// 构建自定义Gson实例
Gson customGson = new GsonBuilder()
        .registerTypeAdapter(BaseItem.class, new ItemTypeAdapter())
        .create();

// 构建Retrofit
Retrofit retrofit = new Retrofit.Builder()
        .baseUrl("你的接口基础URL")
        .addConverterFactory(GsonConverterFactory.create(customGson))
        .build();

之后你的接口就可以直接用Call<List<BaseItem>>来接收数据了,拿到列表后用instanceof判断类型再做后续处理就行。

2. 用RuntimeTypeAdapterFactory(简洁的多态解析)

如果你的对象是基于某个固定字段(比如上面的type)来区分类型的,Gson的扩展库提供了RuntimeTypeAdapterFactory,能让代码更简洁。

第一步:添加依赖

先在你的build.gradle里加Gson扩展库的依赖:

implementation 'com.google.code.gson:gson-extras:2.10.1'

第二步:配置TypeAdapterFactory

这个工厂类会自动根据指定的字段来匹配对应的子类:

RuntimeTypeAdapterFactory<BaseItem> typeAdapterFactory = RuntimeTypeAdapterFactory
        .of(BaseItem.class, "type") // 指定基类和区分字段
        .registerSubtype(ArticleItem.class, "article") // 注册子类和对应的type值
        .registerSubtype(VideoItem.class, "video");

// 构建自定义Gson
Gson customGson = new GsonBuilder()
        .registerTypeAdapterFactory(typeAdapterFactory)
        .create();

剩下的Retrofit配置和接口定义和第一种方法完全一样,这个方式代码量更少,适合类型比较规整的场景。

3. 兜底方案:先解析成JsonObject再手动处理

如果你不想折腾自定义Adapter,或者只是临时验证接口,也可以先把整个数组解析成List<JsonObject>,然后逐个手动解析:

Call<List<JsonObject>> call = apiService.getMixedItems();
call.enqueue(new Callback<List<JsonObject>>() {
    @Override
    public void onResponse(Call<List<JsonObject>> call, Response<List<JsonObject>> response) {
        if (response.isSuccessful() && response.body() != null) {
            List<BaseItem> itemList = new ArrayList<>();
            Gson gson = new Gson();
            for (JsonObject jsonObj : response.body()) {
                String type = jsonObj.get("type").getAsString();
                if ("article".equals(type)) {
                    itemList.add(gson.fromJson(jsonObj, ArticleItem.class));
                } else if ("video".equals(type)) {
                    itemList.add(gson.fromJson(jsonObj, VideoItem.class));
                }
            }
            // 拿到itemList后做业务处理
        }
    }

    @Override
    public void onFailure(Call<List<JsonObject>> call, Throwable t) {
        // 处理请求失败的情况
        Log.e("Retrofit", "请求失败", t);
    }
});

这个方式虽然代码繁琐一点,但胜在直观,适合快速验证或者类型很少的场景。

内容的提问来源于stack exchange,提问作者ProGrammar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 08:19:39