Gson自定义序列化:仅将特定值转为Null并保留对应字段
问题解决方案
问题根源
Gson默认会忽略所有值为null的字段,所以即便你的NullStringSerializer把KEEP_ME转为JsonNull,这个字段还是会被Gson的默认规则过滤掉;同时原生null的lastName也被过滤,最终只留下非null的salary字段。
要实现需求,需要同时满足两个逻辑:
- 保留由
KEEP_ME转换而来的null字段 - 移除原生就是null的字段
方案一:自定义对象级序列化器(精准控制)
直接针对MyObject编写序列化器,逐个字段处理逻辑:
static class MyObjectSerializer implements JsonSerializer<MyObject> { private static final String KEEP_ME = "$$$___KEEP_ME___$$$"; @Override public JsonElement serialize(MyObject src, Type typeOfSrc, JsonSerializationContext context) { JsonObject jsonObject = new JsonObject(); // 处理firstName:KEEP_ME转null并保留,原生null则跳过 if (src.getFirstName() != null) { jsonObject.add("firstName", KEEP_ME.equals(src.getFirstName()) ? JsonNull.INSTANCE : context.serialize(src.getFirstName())); } // 处理lastName:原生null直接跳过,不加入JSON // 处理salary:直接序列化 jsonObject.addProperty("salary", src.getSalary()); return jsonObject; } }
初始化Gson时注册该序列化器:
Gson gson = new GsonBuilder() .registerTypeAdapter(MyObject.class, new MyObjectSerializer()) .create(); System.out.println(gson.toJson(obj));
方案二:结合序列化null配置与排除策略(通用型)
如果需要适配更多类,可通过serializeNulls保留所有null字段,再用自定义策略过滤原生null:
- 简化字符串序列化器,仅处理
KEEP_ME转null:
static class KeepMeToNullSerializer implements JsonSerializer<String> { private static final String KEEP_ME = "$$$___KEEP_ME___$$$"; @Override public JsonElement serialize(String src, Type typeOfSrc, JsonSerializationContext context) { return KEEP_ME.equals(src) ? JsonNull.INSTANCE : context.serialize(src); } }
- 定义排除策略,仅移除原生值为null的字段:
static class ExcludeOriginalNullStrategy implements ExclusionStrategy { @Override public boolean shouldSkipField(FieldAttributes attrs) { return false; } @Override public boolean shouldSkipClass(Class<?> clazz) { return false; } @Override public boolean shouldSkipField(FieldAttributes attrs, Object obj) { try { Field field = attrs.getDeclaringClass().getDeclaredField(attrs.getName()); field.setAccessible(true); // 仅跳过字段原生值为null的情况 return field.get(obj) == null; } catch (Exception e) { return false; } } }
- 初始化Gson时组合配置:
Gson gson = new GsonBuilder() .registerTypeAdapter(String.class, new KeepMeToNullSerializer()) .serializeNulls() // 让Gson保留所有null字段 .setExclusionStrategies(new ExcludeOriginalNullStrategy()) .create(); System.out.println(gson.toJson(obj));
最终输出
两种方案都会得到期望结果:
{"firstName":null,"salary":1000}
内容的提问来源于stack exchange,提问作者Alp
相关产品推荐
相关产品推荐

