我希望在序列化之前修改一个对象。我想编写一个自定义序列化程序来解析对象,然后将其传递给默认对象序列化程序。
这就是我所拥有的:
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<Person>{
@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
,但它非常沉重,并且加载了我的加载时间。
帮助!谢谢!
答案 0 :(得分:7)
由于Jackson 2.2可能会在JsonSerialize注释中使用转换器:
@JsonSerialize(converter = OurConverter.class)
和转换器
public class OurConverter extends StdConverter<IN, OUT>
如果修改对象,IN和OUT是同一类
答案 1 :(得分:6)
神圣的废话,经过几个小时的挖掘这个图书馆,试图写我自己的工厂,以及其他一千件事情,我最终得到了这个愚蠢的事情来做我想要的事情:
public class PersonSerializer extends JsonSerializer<Person>{
@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);
}
}
答案 2 :(得分:5)
虽然我最初对找到@ Nitroware的答案感到高兴,但不幸的是,它在Jackson 2.7.2中无效 - BeanSerializerFactory.instance.createSerializer
再次对JsonSerializer
课程进行Person
内省注释,这导致无限递归和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-09-28:
我发现上面提到的推理错误。使用sole BeanSerializerFactory.constructBeanSerializer
方法是不够的。如果原始类包含空字段,则它们不在输出中。 (原因是constructBeanSerializer
方法是从createAndCacheUntypedSerializer
方法间接调用的,后来调用addAndResolveNonTypedSerializer
方法将NullSerializer
添加到BeanPropertyWriter
s)。)< / p>
这个问题的解决方案对我而言非常简单,重用所有序列化逻辑,而不仅仅是constructBeanSerializer方法。该逻辑从提供者的serializeValue
方法开始。唯一不合适的是自定义JsonSerialize
注释。因此,我们重新定义BeanSerializationFactory
以假装内省类(并且只有它 - 否则J字序化对字段类型的注释不适用)没有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);
}
请注意,如果您没有遇到空值问题,以前的解决方案就足够了。