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

Gson无法将LinkedHashMap作为类字段正确转换为JSON的问题

Gson序列化LinkedHashMap作为类字段时为空的问题解决

直接使用Gson序列化LinkedHashMap<Integer, String>时结果正常,但将其作为父类(Rate)的字段,通过子类(RateChild)嵌套在ZoneChild中序列化时,得到的JSON中该Map为空,输出仅显示"rate": {}。

原因分析

  • 非静态内部类依赖问题:Rate、RateChild等是外部类Example的非静态内部类,实例化时依赖外部类对象,Gson在反射序列化时无法正确访问这类内部类的包私有字段,导致读取到的是字段初始化时的空Map。
  • 泛型类型擦除影响:当泛型Map作为父类字段存在时,Gson默认的反射机制可能无法正确识别其泛型参数,导致序列化失败。

解决方案

方案1:将内部类改为静态内部类

非静态内部类依赖外部类实例,改为静态内部类后摆脱这种依赖,Gson可以正常反射访问字段:

public class Example {
    public static void main(String[] args) {
        Gson gson = new GsonBuilder().setPrettyPrinting().create();
        System.out.println("GSON HashMap!");
        System.out.println(gson.toJson(hashMe()));
        System.out.println("GSON Zone!");
        System.out.print(gson.toJson(zoneMe()));
    }
    
    public static ZoneChild zoneMe() {
        RateChild rate = new RateChild(hashMe());
        ZoneChild zone = new ZoneChild();
        zone.setName("Example");
        zone.setRate(rate);
        return zone;
    }
    
    public static LinkedHashMap<Integer, String> hashMe() {
        LinkedHashMap<Integer, String> rates = new LinkedHashMap<>();
        rates.put(60, "data1");
        rates.put(25, "data2");
        rates.put(15, "data3");
        return rates;
    }
    
    // 所有内部类添加static修饰
    public static class Zone {
        RateChild rate;
        
        public Zone() {}
        public void setRate(RateChild rate) { this.rate = rate; }
    }
    
    public static class ZoneChild extends Zone {
        private int level;
        private String name;
        
        public ZoneChild() {}
        public void setName(String name) { this.name = name; }
        public void setLevel(int level) { this.level = level; }
    }
    
    public static class Rate {
        LinkedHashMap<Integer, String> rate = new LinkedHashMap<>();
        
        public Rate(LinkedHashMap<Integer, String> rate) { this.rate = rate; }
    }
    
    public static class RateChild extends Rate {
        public RateChild(LinkedHashMap<Integer, String> rate) { super(rate); }
    }
}

方案2:修改字段访问权限

将Rate类中的rate字段改为public,确保Gson反射时能直接读取到字段的实际值:

public class Rate {
    public LinkedHashMap<Integer, String> rate = new LinkedHashMap<>();
    
    public Rate(LinkedHashMap<Integer, String> rate) {
        this.rate = rate;
    }
}

方案3:使用TypeToken指定泛型类型

通过TypeToken明确告知Gson待序列化对象的泛型结构,避免类型擦除带来的识别问题:

public static void main(String[] args) {
    Gson gson = new GsonBuilder().setPrettyPrinting().create();
    System.out.println("GSON HashMap!");
    System.out.println(gson.toJson(hashMe()));
    System.out.println("GSON Zone!");
    
    // 用TypeToken指定ZoneChild的类型
    Type zoneChildType = new TypeToken<ZoneChild>() {}.getType();
    System.out.print(gson.toJson(zoneMe(), zoneChildType));
}

验证结果

修改后序列化输出将正确包含LinkedHashMap的所有元素:

{
  "level": 0,
  "name": "Example",
  "rate": {
    "rate": {
      "60": "data1",
      "25": "data2",
      "15": "data3"
    }
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 00:02:05