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

如何用GSON反序列化无成员名的极简API响应为POJO?

如何正确将极简订单簿JSON响应转换为类型安全的POJO(GSON)

咱们先梳理下问题:你调用的这个/api/v1/depth接口返回的订单簿响应里,bids和asks都是固定位置的嵌套列表,但用jsonschema2pojo生成的OrderBook类里只是简单用了List<List<String>>,完全没有体现出每个子列表的结构语义,而且GSON确实没有按位置映射的注解,所以得手动处理这个问题。

下面给你两种实用的解决方案:

方法一:自定义TypeAdapter(推荐用于高频反序列化场景)

这种方式最灵活,性能也最好,直接告诉GSON怎么把嵌套列表转换成我们定义的实体类。

步骤1:定义订单条目实体类

先创建一个OrderEntry类,用来对应每个bids/asks的子列表:

public class OrderEntry {
    private final String price;
    private final String quantity;
    private final List<Void> extra; // 对应第三个空数组,用Void表示无意义的空元素

    // 构造方法+Getter(因为是固定结构,用不可变类更安全)
    public OrderEntry(String price, String quantity, List<Void> extra) {
        this.price = price;
        this.quantity = quantity;
        this.extra = extra;
    }

    public String getPrice() { return price; }
    public String getQuantity() { return quantity; }
    public List<Void> getExtra() { return extra; }
}

步骤2:修改OrderBook类

把原来的嵌套列表换成List<OrderEntry>:

public class OrderBook {
    @SerializedName("lastUpdateId")
    public Long lastUpdateId;
    @SerializedName("bids")
    public List<OrderEntry> bids = null;
    @SerializedName("asks")
    public List<OrderEntry> asks = null;
}

步骤3:编写自定义TypeAdapter

这个适配器负责把JSON里的数组转换成OrderEntry对象:

import com.google.gson.TypeAdapter;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class OrderEntryTypeAdapter extends TypeAdapter<OrderEntry> {

    @Override
    public void write(JsonWriter out, OrderEntry value) throws IOException {
        // 如果需要序列化订单条目,这里实现写入逻辑;如果只反序列化,可以留空或者抛出异常
        out.beginArray();
        out.value(value.getPrice());
        out.value(value.getQuantity());
        out.beginArray();
        out.endArray(); // 第三个元素是空数组
        out.endArray();
    }

    @Override
    public OrderEntry read(JsonReader in) throws IOException {
        in.beginArray(); // 开始读取子列表
        String price = in.nextString(); // 第一个元素:价格
        String quantity = in.nextString(); // 第二个元素:数量
        
        // 处理第三个空数组
        in.beginArray();
        List<Void> emptyList = new ArrayList<>();
        while (in.hasNext()) {
            in.skipValue(); // 因为是空数组,直接跳过所有元素
        }
        in.endArray();
        
        in.endArray(); // 结束子列表读取
        return new OrderEntry(price, quantity, emptyList);
    }
}

步骤4:注册TypeAdapter到Gson实例

在创建Gson对象时注册这个适配器,之后就能正常反序列化了:

Gson gson = new GsonBuilder()
        .registerTypeAdapter(OrderEntry.class, new OrderEntryTypeAdapter())
        .create();

// 示例:反序列化JSON响应
String jsonResponse = "{ \"lastUpdateId\": 1027024, \"bids\": [ [ \"4.00000000\", \"431.00000000\", [] ] ], \"asks\": [ [ \"4.00000200\", \"12.00000000\", [] ] ] }";
OrderBook orderBook = gson.fromJson(jsonResponse, OrderBook.class);

方法二:封装原始列表,提供类型安全的Getter(快速实现)

如果你的场景对性能要求不高,或者不想写TypeAdapter,可以用这种更简洁的方式:保留自动生成的嵌套列表,然后通过Getter方法把它转换成类型安全的OrderEntry列表。

修改后的OrderBook类

import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

public class OrderBook {
    @SerializedName("lastUpdateId")
    public Long lastUpdateId;
    @SerializedName("bids")
    private List<List<String>> rawBids = null; // 隐藏原始列表
    @SerializedName("asks")
    private List<List<String>> rawAsks = null;

    // 提供类型安全的Getter,自动转换原始列表
    public List<OrderEntry> getBids() {
        if (rawBids == null) return Collections.emptyList();
        return rawBids.stream()
                .map(rawEntry -> new OrderEntry(
                        rawEntry.get(0), 
                        rawEntry.get(1), 
                        Collections.emptyList()
                ))
                .collect(Collectors.toList());
    }

    public List<OrderEntry> getAsks() {
        if (rawAsks == null) return Collections.emptyList();
        return rawAsks.stream()
                .map(rawEntry -> new OrderEntry(
                        rawEntry.get(0), 
                        rawEntry.get(1), 
                        Collections.emptyList()
                ))
                .collect(Collectors.toList());
    }

    // 内部静态类:订单条目
    public static class OrderEntry {
        private final String price;
        private final String quantity;
        private final List<Void> extra;

        public OrderEntry(String price, String quantity, List<Void> extra) {
            this.price = price;
            this.quantity = quantity;
            this.extra = extra;
        }

        // Getter方法
        public String getPrice() { return price; }
        public String getQuantity() { return quantity; }
        public List<Void> getExtra() { return extra; }
    }
}

这种方式不需要额外的适配器代码,直接用Java Stream完成转换,适合快速开发。如果担心重复转换的性能问题,可以把转换后的列表缓存起来(比如用lazy加载的方式)。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 09:31:02