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

如何实现泛型Data类兼容JSON中data节点的数组与对象?

解决方案

1. 定义泛型Data类

先统一泛型结构,将data字段定义为集合类型,确保两种JSON格式最终都能解析为统一的实体集合:

public class Data<T> {
    private int code;
    private String message;
    private List<T> data;

    // 构造器、getter、setter方法按需实现
}

2. 自定义泛型TypeAdapterFactory

创建适配器工厂,自动识别并处理单个对象/数组的兼容解析,同时支持泛型适配不同实体类(如Client、Provider):

import com.google.gson.*;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;

public class SingleOrArrayTypeAdapterFactory implements TypeAdapterFactory {

    @SuppressWarnings("unchecked")
    @Override
    public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
        // 仅处理List类型字段
        if (!List.class.isAssignableFrom(type.getRawType())) {
            return null;
        }
        // 获取List的泛型参数类型(如Client、Provider)
        Type elementType = ((ParameterizedType) type.getType()).getActualTypeArguments()[0];
        TypeAdapter<?> elementAdapter = gson.getAdapter(TypeToken.get(elementType));

        return (TypeAdapter<T>) new TypeAdapter<List<?>>() {
            @Override
            public void write(JsonWriter out, List<?> value) throws IOException {
                // 序列化逻辑:列表仅1个元素时输出为单个对象,否则输出数组(按需可调整为始终输出数组)
                if (value.size() == 1) {
                    elementAdapter.write(out, value.get(0));
                } else {
                    out.beginArray();
                    for (Object item : value) {
                        elementAdapter.write(out, item);
                    }
                    out.endArray();
                }
            }

            @Override
            public List<?> read(JsonReader in) throws IOException {
                List<Object> resultList = new ArrayList<>();
                JsonToken token = in.peek();
                if (token == JsonToken.BEGIN_OBJECT) {
                    // 单个对象场景:解析后加入集合
                    Object item = elementAdapter.read(in);
                    resultList.add(item);
                } else if (token == JsonToken.BEGIN_ARRAY) {
                    // 数组场景:逐个解析元素加入集合
                    in.beginArray();
                    while (in.hasNext()) {
                        Object item = elementAdapter.read(in);
                        resultList.add(item);
                    }
                    in.endArray();
                }
                return resultList;
            }
        };
    }
}

3. 注册适配器并执行反序列化

创建Gson实例时注册自定义适配器,即可兼容两种JSON格式的解析:

// 初始化带适配器的Gson实例
Gson gson = new GsonBuilder()
        .registerTypeAdapterFactory(new SingleOrArrayTypeAdapterFactory())
        .create();

// 解析单个Client对象的JSON
String singleClientJson = "{\"code\":200,\"message\":\"success\",\"data\":{\"id\":1,\"name\":\"ClientA\"}}";
Data<Client> singleData = gson.fromJson(singleClientJson, new TypeToken<Data<Client>>() {}.getType());

// 解析Client数组的JSON
String arrayClientJson = "{\"code\":200,\"message\":\"success\",\"data\":[{\"id\":1,\"name\":\"ClientA\"},{\"id\":2,\"name\":\"ClientB\"}]}";
Data<Client> arrayData = gson.fromJson(arrayClientJson, new TypeToken<Data<Client>>() {}.getType());

// 同样适配Provider类
String providerJson = "{\"code\":200,\"message\":\"success\",\"data\":{\"id\":101,\"name\":\"ProviderX\"}}";
Data<Provider> providerData = gson.fromJson(providerJson, new TypeToken<Data<Provider>>() {}.getType());

核心说明

  • 适配器会自动识别data节点的类型(单个对象/数组),统一解析为List<T>,完美适配泛型Data类;
  • 序列化时可根据列表长度自动切换输出格式,也可修改write方法强制始终输出数组。

内容的提问来源于stack exchange,提问作者Iñigo Dominguez

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 20:15:41