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

使用GSON从嵌套类取值并在构造方法中赋值的问题

解决GSON反序列化时构造方法依赖字段为null的问题

嘿,我刚踩过类似的坑,来给你捋清楚怎么搞定这个问题~

首先得明确GSON默认的反序列化逻辑:它会先创建类的实例(要么调用无参构造,要么用Unsafe绕开构造直接生成对象),然后才会把JSON里的字段值通过反射赋值给类的成员变量。所以你在Class1的构造方法里去拿className肯定是null——因为这时候GSON还没给这个字段赋值呢!

那要实现「从子类(不管是JSON里的子结构还是Java子类)取值并在构造方法中赋值」,有几个靠谱的方案:

方案1:自定义JsonDeserializer手动控制实例创建

这是最直接的解决办法,你可以自己接管反序列化的全过程,先从JSON里把需要的className(包括子类嵌套结构里的)取出来,再调用带参数的构造方法创建实例,最后把其他字段也补上。

举个代码例子:

public class Class1Deserializer implements JsonDeserializer<Class1> {
    @Override
    public Class1 deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
        // 先把JSON元素转成JsonObject
        JsonObject jsonObj = json.getAsJsonObject();
        
        // 假设className在子类的嵌套结构里,比如JSON里有个"subClass"对象包含它
        String className = jsonObj.getAsJsonObject("subClass")
                                 .get("className")
                                 .getAsString();
        
        // 用拿到的className调用带参构造,不会再出现null的情况
        Class1 class1Instance = new Class1(className);
        
        // 让GSON帮你处理剩下的字段赋值
        context.deserialize(json, Class1.class);
        
        return class1Instance;
    }
}

然后把这个反序列化器注册到GSON中:

Gson gson = new GsonBuilder()
    .registerTypeAdapter(Class1.class, new Class1Deserializer())
    .create();

// 反序列化JSON数组
List<Class1> class1List = gson.fromJson(jsonArrayStr, new TypeToken<List<Class1>>(){}.getType());

方案2:重构代码,把构造逻辑移到初始化方法

如果不想写自定义反序列化器,最简单的方式就是把构造方法里依赖className的逻辑抽出来,放到一个单独的初始化方法里,等GSON完成反序列化后再手动调用。

比如:

public class Class1 {
    private String className;

    // 保留无参构造,让GSON能正常创建实例
    public Class1() {}

    // 初始化方法,反序列化完成后调用
    public void init() {
        if (className == null) {
            throw new IllegalArgumentException("className 不能为null");
        }
        // 原来构造方法里的逻辑全移到这里
    }
}

然后反序列化后遍历执行初始化:

List<Class1> class1List = gson.fromJson(jsonArrayStr, new TypeToken<List<Class1>>(){}.getType());
for (Class1 item : class1List) {
    item.init();
}

额外提醒:检查字段映射是否正确

有时候className为null可能只是因为JSON里的字段名和Java类里的字段名不匹配,比如JSON里是class_name但Java里是className,这时候可以用@SerializedName注解来做映射:

public class Class1 {
    @SerializedName("class_name") // 对应JSON里的字段名
    private String className;

    // ...
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 04:36:04