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

如何在Java中用Gson反序列化含动态键名的JSON对象?

Gson处理动态键名JSON反序列化的方案

问题场景

我在开发首个个人项目时,被API返回JSON的反序列化问题困扰了好几天。目前用Gson包处理JSON对象,Gson默认要求Java类变量名和JSON键名匹配,否则会忽略字段。

我的代码结构如下:

public class partsAvailability {
private partNumber partNumber;

public partNumber getpartNumber() {
    return partNumber;
}

public void setpartNumber(partNumber partnumber) {
    this.partNumber = partnumber;
}

public class partNumber {
private String pickupSearchQuote;

public String getPickupSearchQuote() {
    return pickupSearchQuote;
}

public void setPickupSearchQuote(String pickupSearchQuote) {
    this.pickupSearchQuote = pickupSearchQuote;
}
}

对应的API返回JSON片段:

"partsAvailability": {
    "MQ8R3LL/A": {
        "pickupSearchQuote": "Unavailable for Pickup"
    }
}

问题在于partsAvailability下的键是随请求变化的零件编号(比如MQ8R3LL/A),没法提前用这个动态值命名Java类,想找到不用动态命名类就能获取内部信息的方法。


已解决方案及优化建议

我已经解决了问题:发现JSON被映射成LinkedTreeMap格式,因为只需要其中3-4条信息,所以用了getAsJsonObject()和getAsJsonArray()方法手动解析。针对这个方案,有以下优化方向:

1. 简化手动解析代码

如果明确知道目标零件编号,可以直接链式调用获取字段,避免多余的中间变量:

// 假设已将顶层JSON解析为JsonObject root
String pickupQuote = root.getAsJsonObject("partsAvailability")
                         .getAsJsonObject("MQ8R3LL/A")
                         .get("pickupSearchQuote")
                         .getAsString();

如果需要遍历所有动态零件编号,可以直接遍历JsonObject的entrySet:

JsonObject partsAvail = root.getAsJsonObject("partsAvailability");
for (Map.Entry<String, JsonElement> entry : partsAvail.entrySet()) {
    String partId = entry.getKey();
    String quote = entry.getValue().getAsJsonObject().get("pickupSearchQuote").getAsString();
    // 处理每个零件的信息
}

2. 结构化解析方案(适合需要复用或多字段场景)

如果后续需要获取更多字段,或者想让代码更结构化,推荐用Map<String, PartNumber>替代固定字段,让Gson自动映射动态键:

修改Java类:

// 注意类名遵循大驼峰规范
public class PartsAvailability {
    // 用Map存储动态键值对,key是零件编号,value是对应的数据对象
    @SerializedName("partsAvailability")
    private Map<String, PartNumber> partMap;

    public Map<String, PartNumber> getPartMap() {
        return partMap;
    }

    public void setPartMap(Map<String, PartNumber> partMap) {
        this.partMap = partMap;
    }
}

public class PartNumber {
    private String pickupSearchQuote;

    public String getPickupSearchQuote() {
        return pickupSearchQuote;
    }

    public void setPickupSearchQuote(String pickupSearchQuote) {
        this.pickupSearchQuote = pickupSearchQuote;
    }
}

反序列化时直接转成PartsAvailability类,之后通过Map操作获取数据:

PartsAvailability avail = gson.fromJson(jsonStr, PartsAvailability.class);
// 获取指定零件的信息
PartNumber part = avail.getPartMap().get("MQ8R3LL/A");
if (part != null) {
    String quote = part.getPickupSearchQuote();
}
// 遍历所有零件
for (Map.Entry<String, PartNumber> entry : avail.getPartMap().entrySet()) {
    // 处理数据
}

这种方案的优势是代码更符合面向对象规范,后续扩展字段时只需要修改PartNumber类即可,无需调整解析逻辑。


内容的提问来源于stack exchange,提问作者the-beef-calculator

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 09:35:16