虽然我最初很高兴找到@Nitroware 的答案,但不幸的是它在Jackson 2.7.2 中不起作用-BeanSerializerFactory.instance.createSerializer 再次对Person 类进行内省JsonSerializer 注释,这会导致无限递归和StackOverflowError。
如果 POJO 类上不存在 @JsonSerializer,则创建默认序列化程序的点是 BeanSerializerFactory.constructBeanSerializer 方法。所以我们直接使用这个方法。由于方法是protected,我们通过工厂子类使其可见,并为其提供有关序列化类的信息。此外,我们将已弃用的 SimpleType.construct 方法替换为推荐的替换方法。整个解决方案是:
public class PersonSerializer extends JsonSerializer<PersonSerializer> {
static class BeanSerializerFactoryWithVisibleConstructingMethod extends BeanSerializerFactory {
BeanSerializerFactoryWithVisibleConstructingMethod() {
super(BeanSerializerFactory.instance.getFactoryConfig());
}
@Override
public JsonSerializer<Object> constructBeanSerializer(SerializerProvider prov, BeanDescription beanDesc) throws JsonMappingException {
return super.constructBeanSerializer(prov, beanDesc);
}
}
private final BeanSerializerFactoryWithVisibleConstructingMethod defaultBeanSerializerFactory = new BeanSerializerFactoryWithVisibleConstructingMethod();
private final JavaType javaType = TypeFactory.defaultInstance().constructType(Person.class);
@Override
public void serialize(Person value, JsonGenerator jgen, SerializerProvider provider) throws IOException {
Person safePerson = PrivacyService.getSafePerson(value);
JavaType type = TypeFactory.defaultInstance().constructType(Person.class);
BeanDescription beanDescription = provider.getConfig().introspect(type);
JsonSerializer<Object> defaultSerializer = defaultBeanSerializerFactory.constructBeanSerializer(provider, beanDescription);
defaultSerializer.serialize(safePerson, jgen, provider);
}
}
与基于BeanSerializerModifier 的解决方案不同,您必须在自定义序列化程序之外声明和注册特殊行为,在此解决方案中,特殊逻辑仍封装在自定义PersonSerializer 中。
最终逻辑可能会被推送到自定义 DefaultJsonSerializerAware 祖先。
2017 年 9 月 28 日更新:
我在上述推理中发现了错误。仅使用BeanSerializerFactory.constructBeanSerializer 方法是不够的。如果原始类包含空字段,则它们不在输出中。 (原因是constructBeanSerializer方法是从createAndCacheUntypedSerializer方法间接调用的,该方法后来调用addAndResolveNonTypedSerializer方法,其中NullSerializers被添加到BeanPropertyWriters中。)
这个问题的解决方案对我来说似乎是正确的并且非常简单重用所有序列化逻辑,而不仅仅是constructBeanSerializer方法。这个逻辑从提供者的serializeValue 方法开始。唯一不合适的是自定义 JsonSerialize 注释。因此,我们重新定义 BeanSerializationFactory 以假装自省类(并且只有它 - 否则字段类型上的 JsonSerialize 注释将不适用)没有 JsonSerialize 注释。
@Override
public void serialize(Person value, JsonGenerator jgen, SerializerProvider provider) throws IOException {
Person safePerson = PrivacyService.getSafePerson(value);
ObjectMapper objectMapper = (ObjectMapper)jgen.getCodec();
Class<?> entityClass = value.getClass();
JavaType javaType = TypeFactory.defaultInstance().constructType(entityClass);
DefaultSerializerProvider.Impl defaultSerializerProvider = (DefaultSerializerProvider.Impl) objectMapper.getSerializerProviderInstance();
BeanSerializerFactory factoryIgnoringCustomSerializerOnRootClass = new BeanSerializerFactory(BeanSerializerFactory.instance.getFactoryConfig()) {
@Override
protected JsonSerializer<Object> findSerializerFromAnnotation(SerializerProvider prov, Annotated a) throws JsonMappingException {
JsonSerializer<Object> result = javaType.equals(a.getType()) ? null : super.findSerializerFromAnnotation(prov, a);
return result;
}
};
DefaultSerializerProvider.Impl updatedSerializerProvider = defaultSerializerProvider.createInstance(defaultSerializerProvider.getConfig(), factoryIgnoringCustomSerializerOnRootClass);
updatedSerializerProvider.serializeValue(jgen, value);
}
请注意,如果您没有遇到空值问题,以前的解决方案对您来说就足够了。