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

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:

  1. 简化字符串序列化器,仅处理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);
    }
}
  1. 定义排除策略,仅移除原生值为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;
        }
    }
}
  1. 初始化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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 17:22:15