如何在Retrofit中修改JSON响应体,直接获取List对象
直接解析外层含items的JSON为List(Retrofit+Gson)
不用再写UserRepresentation这类冗余的包装类,通过自定义Gson类型适配器就能实现让Retrofit直接返回List<User>这类结果,具体步骤如下:
1. 编写通用的TypeAdapterFactory
这个工厂类会自动识别List类型的解析请求,跳过外层的items包装,直接解析内部的数组元素:
public class ListResponseTypeAdapterFactory implements TypeAdapterFactory { @SuppressWarnings("unchecked") @Override public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) { // 仅处理List类型 if (!(type.getType() instanceof ParameterizedType) || !List.class.isAssignableFrom((Class<?>) ((ParameterizedType) type.getType()).getRawType())) { return null; } // 获取List的泛型实体类型(比如List<User>里的User) 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 { // 若请求需要包裹成items结构,可在此实现;仅处理响应的话可保留默认数组写法 out.beginArray(); for (Object item : value) { elementAdapter.write(out, item); } out.endArray(); } @Override public List<?> read(JsonReader in) throws IOException { in.beginObject(); List<Object> resultList = new ArrayList<>(); while (in.hasNext()) { String fieldName = in.nextName(); if ("items".equals(fieldName)) { // 解析items数组内的实体 in.beginArray(); while (in.hasNext()) { resultList.add(elementAdapter.read(in)); } in.endArray(); } else { // 忽略响应中的其他无关字段 in.skipValue(); } } in.endObject(); return resultList; } }; } }
2. 配置Gson并注入Retrofit
把自定义的适配器工厂注册到Gson实例中,再配置给Retrofit:
// 构建自定义Gson实例 Gson customGson = new GsonBuilder() .registerTypeAdapterFactory(new ListResponseTypeAdapterFactory()) .create(); // 初始化Retrofit时使用这个自定义Gson Retrofit retrofit = new Retrofit.Builder() .baseUrl("你的API基础地址") .addConverterFactory(GsonConverterFactory.create(customGson)) .build();
3. 修改Retrofit接口方法签名
现在可以直接在接口里用Call<List<实体类>>的形式,无需再定义包装类:
public interface ApiService { @GET("users") Call<List<User>> getUsers(); @GET("repos") Call<List<Repo>> getRepos(); }
额外说明
- 如果API返回的外层包裹字段不是
items,只需修改适配器中"items"的字符串为对应字段名即可; - 若需要处理响应中的其他必填字段(比如总页数),可以在read方法中添加对应解析逻辑;
- 若POST请求需要把列表包裹成
{"items": [...]}的结构,完善write方法的逻辑即可。
内容的提问来源于stack exchange,提问作者hhrzc
相关产品推荐
相关产品推荐

