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

如何让Jackson将指定静态对象NULL_VALUE序列化为null?

问题描述

我尝试序列化一个包含无法修改对象的列表,该列表引用了一个静态对象:

final public static Object NULL_VALUE = new Object() { public String toString() { return "null"; }};

如何配置Jackson将NULL_VALUE对象序列化为null?我尝试了以下自定义序列化器:

public class NullValueSerializer extends StdSerializer<Object> {
    public NullValueSerializer() {
        super(Object.class);
    }

    @Override
    public void serialize(Object value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        if (value == Jsonata.NULL_VALUE) {
            gen.writeNull();
        } else {
            gen.writePOJO(value);
        }
    }
}

本以为此方案可行,但显然出现了StackOverflowError,原因是序列化器递归调用自身。我未找到文档中有相关解决方法,请问是否存在将该值序列化为null的可行方案?

可行解决方案

递归问题的核心是调用gen.writePOJO(value)时,Jackson会再次使用当前绑定的NullValueSerializer处理对象,触发无限递归。以下是几种可行的解决思路:

1. 调用默认序列化器处理非目标对象

避免直接使用writePOJO,转而获取Jackson原生的默认序列化器来处理非NULL_VALUE的对象:

public class NullValueSerializer extends StdSerializer<Object> {
    public NullValueSerializer() {
        super(Object.class);
    }

    @Override
    public void serialize(Object value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        if (value == Jsonata.NULL_VALUE) {
            gen.writeNull();
        } else {
            // 获取Object类型的默认序列化器
            JsonSerializer<Object> defaultSerializer = serializers.findValueSerializer(Object.class, null);
            // 绕过当前序列化器执行序列化,避免递归
            defaultSerializer.unwrappingSerializer(null).serialize(value, gen, serializers);
        }
    }
}

2. 针对具体类型注册序列化器

由于NULL_VALUE是匿名内部类的实例,可直接针对该具体类型注册序列化器,而非覆盖整个Object类的序列化逻辑,从根源避免递归:

// 获取NULL_VALUE的实际类型
Class<?> nullValueType = Jsonata.NULL_VALUE.getClass();

// 注册自定义序列化器
ObjectMapper mapper = new ObjectMapper();
SimpleModule module = new SimpleModule();
module.addSerializer(nullValueType, new StdSerializer<Object>(nullValueType) {
    @Override
    public void serialize(Object value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        gen.writeNull();
    }
});
mapper.registerModule(module);

这种方式更高效,仅对NULL_VALUE实例生效,不影响其他对象的正常序列化流程。

3. 通过BeanSerializerModifier全局拦截

如果需要全局范围内处理该对象,可使用BeanSerializerModifier拦截序列化过程:

ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new SimpleModule() {
    @Override
    public void setupModule(SetupContext context) {
        super.setupModule(context);
        context.addBeanSerializerModifier(new BeanSerializerModifier() {
            @Override
            public JsonSerializer<?> modifySerializer(SerializationConfig config, BeanDescription beanDesc, JsonSerializer<?> serializer) {
                return new JsonSerializer<Object>() {
                    @Override
                    public void serialize(Object value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
                        if (value == Jsonata.NULL_VALUE) {
                            gen.writeNull();
                        } else {
                            // 调用原序列化器处理其他对象
                            serializer.serialize(value, gen, serializers);
                        }
                    }
                };
            }
        });
    }
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 14:22:42