Gson反序列化时,标记为不反序列化的字段为何为null?
Gson反序列化时标记不反序列化的final字段为null的问题分析与解决
问题原因
- 反序列化Entity时,Gson会识别JSON里的
setting字段,重新创建Mode实例,不会复用Entity类里预先初始化好的setting对象。 - Mode的
list是final字段,且通过@Expose(deserialize = false)标记为不参与反序列化,Gson会跳过这个字段的赋值操作。 - 因为Mode没有无参构造器,Gson会通过反射绕过构造器创建实例,这时final字段
list会被初始化为默认值null(正常情况下final字段必须在构造器或初始化块里赋值,但反射创建实例时不会执行构造器逻辑)。
解决方案
方案1:给Mode构造器添加参数处理逻辑
修改Mode类的构造器,当传入的list为null时(因为反序列化被排除,Gson会传null),用默认值初始化:
public class Mode { @Expose(deserialize = false) public final List<String> list; public Mode(@SerializedName("list") List<String> list) { // 当list为null时使用默认列表 this.list = list != null ? list : Arrays.asList("1", "2"); } public List<String> getList() { return list; } }
Gson默认会识别带参数的构造器,配合@SerializedName可以让构造器参数和JSON字段对应,这样反序列化时即使list被排除,也能通过构造器给final字段赋默认值。
方案2:自定义InstanceCreator创建Mode实例
写一个InstanceCreator,让Gson在创建Mode实例时直接返回带默认list的对象:
public class ModeInstanceCreator implements InstanceCreator<Mode> { @Override public Mode createInstance(Type type) { return new Mode(Arrays.asList("1", "2")); } }
然后在Gson构建时注册这个InstanceCreator:
Gson gson = new GsonBuilder() .setPrettyPrinting() .addDeserializationExclusionStrategy(new ExclusionStrategy() { @Override public boolean shouldSkipField(FieldAttributes f) { Expose annotation = f.getAnnotation(Expose.class); return annotation != null && !annotation.deserialize(); } @Override public boolean shouldSkipClass(Class<?> clazz) { return false; } }) .registerTypeAdapter(Mode.class, new ModeInstanceCreator()) .create();
这样Gson反序列化Mode时,会用InstanceCreator创建实例,list就会是预设的默认值。
方案3:跳过setting字段的反序列化(如果不需要更新setting)
如果不需要从JSON更新setting的内容,只想保留Entity里初始化的setting实例,可以给setting字段加上@Expose(deserialize = false):
public class Entity { @Expose(deserialize = false) public Mode setting = new Mode(Arrays.asList("1", "2")); }
这样Gson会跳过反序列化setting字段,直接保留原来的实例,list自然不会为null。
内容的提问来源于stack exchange,提问作者Enaium
相关产品推荐
相关产品推荐

