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
相关产品推荐
相关产品推荐

