Jackson JSON在序列化之前修改对象

我希望在序列化之前修改一个对象。 我想编写一个自定义序列化程序来解析对象,然后将其传递给默认对象序列化程序。

这就是我所拥有的:

import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.SerializerProvider; import java.io.IOException; /** * * @author Me */ public class PersonSerializer extends JsonSerializer{ @Override public void serialize(Person value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException { //This returns a modified clone of Person value. Person safePerson = PrivacyService.getSafePerson(value); provider.defaultSerializeValue(safePerson, jgen); } } 

但这只是一个无限循环。 我也尝试过:

 provider.findTypedValueSerializer(Person.class, true, null).serialize(safePerson, jgen, provider); 

这可行,但它不解析对象中的任何字段。

我也试过使用@JsonFilter但它非常沉重,并且加载了我的加载时间。

救命! 谢谢!

虽然我最初对找到@ Nitroware的答案感到高兴,但遗憾的是它在Jackson 2.7.2中不起作用 – BeanSerializerFactory.instance.createSerializer再次在Person类上内省JsonSerializer注释,这导致无限递归和StackOverflowError

如果POJO类上没有@JsonSerializer则创建默认序列化程序的点是BeanSerializerFactory.constructBeanSerializer方法。 所以我们直接使用这个方法吧。 由于该方法protected ,我们通过工厂子类使其可见,并向其提供有关序列化类的信息。 此外,我们通过推荐的替换方法替换弃用的SimpleType.construct方法。 整个解决方案是:

 public class PersonSerializer extends JsonSerializer { static class BeanSerializerFactoryWithVisibleConstructingMethod extends BeanSerializerFactory { BeanSerializerFactoryWithVisibleConstructingMethod() { super(BeanSerializerFactory.instance.getFactoryConfig()); } @Override public JsonSerializer 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 defaultSerializer = defaultBeanSerializerFactory.constructBeanSerializer(provider, beanDescription); defaultSerializer.serialize(safePerson, jgen, provider); } } 

与基于BeanSerializerModifier的解决方案不同,您必须在自定义序列化程序之外声明和注册特殊行为,使用此解决方案时,特殊逻辑仍然封装在自定义PersonSerializer

最终逻辑可能被推到自定义DefaultJsonSerializerAware祖先。

更新2017-09-28:

我发现上面提到的推理错误。 使用唯一的BeanSerializerFactory.constructBeanSerializer方法是不够的。 如果原始类包含空字段,则它们不在输出中。 (原因是从createAndCacheUntypedSerializer方法间接调用addAndResolveNonTypedSerializer方法,该方法稍后调用addAndResolveNonTypedSerializer方法,其中将NullSerializer添加到BeanPropertyWriter )。)

解决这个问题对我来说似乎是正确的并且非常简单,就是重用所有序列化逻辑,而不仅仅是constructBeanSerializer方法 。 此逻辑从提供程序的serializeValue方法开始。 唯一不合适的是自定义JsonSerialize注释。 因此,我们重新定义BeanSerializationFactory以假装内省类(并且只有它 – 否则J字节上的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 findSerializerFromAnnotation(SerializerProvider prov, Annotated a) throws JsonMappingException { JsonSerializer result = javaType.equals(a.getType()) ? null : super.findSerializerFromAnnotation(prov, a); return result; } }; DefaultSerializerProvider.Impl updatedSerializerProvider = defaultSerializerProvider.createInstance(defaultSerializerProvider.getConfig(), factoryIgnoringCustomSerializerOnRootClass); updatedSerializerProvider.serializeValue(jgen, value); } 

请注意,如果您没有遇到空值问题,以前的解决方案就足够了。

神圣的废话,经过几个小时的挖掘这个图书馆,试图写我自己的工厂,以及其他一千个东西,我最终得到了这个愚蠢的事情做我想要的:

 public class PersonSerializer extends JsonSerializer{ @Override public void serialize(Person value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException { Person safePerson = PrivacyService.getSafePerson(value); //This is the crazy one-liner that will save someone a very long time BeanSerializerFactory.instance.createSerializer(provider, SimpleType.construct(Person.class)).serialize(safePerson, jgen, provider); } } 

从Jackson 2.2开始,可以在JsonSerialize注释中使用转换器:

@JsonSerialize(converter = OurConverter.class)

和转换器

public class OurConverter extends StdConverter

如果修改对象,IN和OUT是同一类