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

如何用Gson/Jackson将JSON列表包装为带Map的对象(纯Java无Spring)

刚好之前做过类似的纯Java API客户端需求,给你分享下用Gson和Jackson分别实现的具体方案,完全不用Spring这类框架,完美匹配你的场景~

首先先明确下你提到的两种JSON结构示例,方便后续代码对应:

第一种(任意键但字段相同的对象):

{
  "item_001": {"id": 1, "name": "Apple"},
  "item_002": {"id": 2, "name": "Banana"},
  "item_003": {"id": 3, "name": "Cherry"}
}

需要转成包含列表的包装对象(比如ItemListWrapper,里面有List<Item>)

第二种(带列表的对象):

{
  "code": 200,
  "message": "success",
  "data": [{"id":1,"name":"Apple"}, {"id":2,"name":"Banana"}]
}

直接转成对应结构的对象(比如ApiResponse<Item>)


用Gson实现的方案

1. 先定义基础模型类

先把需要的实体类和包装类写好:

// 基础数据实体
class Item {
    private int id;
    private String name;
    
    // 自动生成getter、setter、toString方法即可
}

// 第一种JSON对应的包装类
class ItemListWrapper {
    private List<Item> items;

    public ItemListWrapper(List<Item> items) {
        this.items = items;
    }

    // getter、setter方法
    public List<Item> getItems() { return items; }
    public void setItems(List<Item> items) { this.items = items; }
}

// 第二种JSON的通用响应类
class ApiResponse<T> {
    private int code;
    private String message;
    private List<T> data;
    
    // 自动生成getter、setter、toString方法
}

2. 自定义反序列化器处理第一种JSON

因为第一种JSON是键值对结构,需要把所有值提取出来转成列表,再包装到ItemListWrapper里,所以写个自定义反序列化器:

import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.JsonDeserializationContext;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

class ItemListWrapperDeserializer implements JsonDeserializer<ItemListWrapper> {
    @Override
    public ItemListWrapper deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
        JsonObject jsonObject = json.getAsJsonObject();
        List<Item> items = new ArrayList<>();
        
        // 遍历所有键值对,把值转成Item对象加入列表
        for (Map.Entry<String, JsonElement> entry : jsonObject.entrySet()) {
            Item item = context.deserialize(entry.getValue(), Item.class);
            items.add(item);
        }
        
        return new ItemListWrapper(items);
    }
}

3. 构建通用API客户端

写一个通用的客户端类,支持传入期望的响应类型,自动处理两种JSON结构:

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

class GsonApiClient {
    private final Gson gson;

    public GsonApiClient() {
        // 注册自定义反序列化器,让Gson识别第一种JSON的处理逻辑
        this.gson = new GsonBuilder()
                .registerTypeAdapter(ItemListWrapper.class, new ItemListWrapperDeserializer())
                .create();
    }

    // 处理非泛型的响应类型(比如ItemListWrapper)
    public <T> T fetchData(String apiUrl, Class<T> responseType) throws Exception {
        HttpURLConnection conn = (HttpURLConnection) new URL(apiUrl).openConnection();
        conn.setRequestMethod("GET");

        try (BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()))) {
            StringBuilder response = new StringBuilder();
            String line;
            while ((line = reader.readLine()) != null) {
                response.append(line);
            }
            return gson.fromJson(response.toString(), responseType);
        } finally {
            conn.disconnect();
        }
    }

    // 处理带泛型的响应类型(比如ApiResponse<Item>)
    public <T> T fetchGenericData(String apiUrl, TypeToken<T> typeToken) throws Exception {
        HttpURLConnection conn = (HttpURLConnection) new URL(apiUrl).openConnection();
        conn.setRequestMethod("GET");

        try (BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()))) {
            StringBuilder response = new StringBuilder();
            String line;
            while ((line = reader.readLine()) != null) {
                response.append(line);
            }
            return gson.fromJson(response.toString(), typeToken.getType());
        } finally {
            conn.disconnect();
        }
    }
}

4. 使用示例

public class Main {
    public static void main(String[] args) throws Exception {
        GsonApiClient client = new GsonApiClient();

        // 处理第一种JSON,转成ItemListWrapper
        String url1 = "https://your-api.com/items-as-map";
        ItemListWrapper wrapper = client.fetchData(url1, ItemListWrapper.class);
        System.out.println("第一种JSON处理结果:" + wrapper.getItems());

        // 处理第二种JSON,转成ApiResponse<Item>
        String url2 = "https://your-api.com/items-as-list";
        ApiResponse<Item> response = client.fetchGenericData(url2, new TypeToken<ApiResponse<Item>>() {});
        System.out.println("第二种JSON处理结果:" + response.getData());
    }
}

用Jackson实现的方案

如果你更倾向于Codehaus Jackson(不过现在主流是FasterXML Jackson,这里用FasterXML的示例,API和Codehaus类似,调整依赖即可):

1. 定义模型类

和Gson的模型类基本一致,可添加Jackson注解辅助序列化:

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;

class Item {
    private int id;
    private String name;
    
    // getter、setter、toString
}

class ItemListWrapper {
    private List<Item> items;

    @JsonCreator
    public ItemListWrapper(@JsonProperty("items") List<Item> items) {
        this.items = items;
    }

    // getter、setter
}

class ApiResponse<T> {
    private int code;
    private String message;
    private List<T> data;
    
    // getter、setter、toString
}

2. 自定义反序列化器

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonNode;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

class ItemListWrapperDeserializer extends JsonDeserializer<ItemListWrapper> {
    @Override
    public ItemListWrapper deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
        JsonNode rootNode = p.getCodec().readTree(p);
        List<Item> items = new ArrayList<>();
        
        // 遍历所有子节点,转成Item对象
        Iterator<JsonNode> elements = rootNode.elements();
        while (elements.hasNext()) {
            JsonNode itemNode = elements.next();
            Item item = p.getCodec().treeToValue(itemNode, Item.class);
            items.add(item);
        }
        
        return new ItemListWrapper(items);
    }
}

3. 构建API客户端

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.core.type.TypeReference;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

class JacksonApiClient {
    private final ObjectMapper objectMapper;

    public JacksonApiClient() {
        this.objectMapper = new ObjectMapper();
        // 注册自定义反序列化器
        SimpleModule module = new SimpleModule();
        module.addDeserializer(ItemListWrapper.class, new ItemListWrapperDeserializer());
        objectMapper.registerModule(module);
    }

    // 处理非泛型类型
    public <T> T fetchData(String apiUrl, Class<T> responseType) throws Exception {
        HttpURLConnection conn = (HttpURLConnection) new URL(apiUrl).openConnection();
        conn.setRequestMethod("GET");

        try (BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()))) {
            return objectMapper.readValue(reader, responseType);
        } finally {
            conn.disconnect();
        }
    }

    // 处理带泛型的类型
    public <T> T fetchGenericData(String apiUrl, TypeReference<T> typeRef) throws Exception {
        HttpURLConnection conn = (HttpURLConnection) new URL(apiUrl).openConnection();
        conn.setRequestMethod("GET");

        try (BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()))) {
            return objectMapper.readValue(reader, typeRef);
        } finally {
            conn.disconnect();
        }
    }
}

4. 使用示例

public class Main {
    public static void main(String[] args) throws Exception {
        JacksonApiClient client = new JacksonApiClient();

        // 处理第一种JSON
        String url1 = "https://your-api.com/items-as-map";
        ItemListWrapper wrapper = client.fetchData(url1, ItemListWrapper.class);
        System.out.println("第一种JSON处理结果:" + wrapper.getItems());

        // 处理第二种JSON
        String url2 = "https://your-api.com/items-as-list";
        ApiResponse<Item> response = client.fetchGenericData(url2, new TypeReference<ApiResponse<Item>>() {});
        System.out.println("第二种JSON处理结果:" + response.getData());
    }
}

一些额外注意点

  • 依赖方面:Gson只需要引入com.google.code.gson:gson;Jackson引入com.fasterxml.jackson.core:jackson-databind即可(Codehaus Jackson的话依赖是org.codehaus.jackson:jackson-mapper-asl,API略有不同但核心逻辑一致)。
  • 如果第一种JSON的键有业务价值,你可以修改包装类,比如改成List<Map.Entry<String, Item>>或者自定义NamedItem类(包含键和Item对象),只需要调整反序列化器的逻辑即可。
  • 客户端的HTTP请求部分可以按需扩展,比如添加请求头、支持POST方法、超时设置等,上面的示例是最基础的GET请求实现。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 09:07:03