Java 更改属性的活动视图
使用Jackson,我希望能够在序列化属性时更改活动视图 因此,如果我的应用程序使用3个视图A、B和C,我可能希望类型T的属性p始终使用视图A进行序列化,而不管活动视图Java 更改属性的活动视图,java,json,jackson,Java,Json,Jackson,使用Jackson,我希望能够在序列化属性时更改活动视图 因此,如果我的应用程序使用3个视图A、B和C,我可能希望类型T的属性p始终使用视图A进行序列化,而不管活动视图Class是null,A.Class,B.Class,还是C.Class 我还没有找到任何内置于Jackson中的方法来实现这一点,所以我计划制作自己的类来实现这一点 在我可能重新发明轮子之前,对于普通的Jackson注释和/或类,这可能吗 如果没有,我计划做如下的事情(注意:为了简化这个问题,我省略了很多配置选项和性能优化,这些
Class
是null
,A.Class
,B.Class
,还是C.Class
我还没有找到任何内置于Jackson中的方法来实现这一点,所以我计划制作自己的类来实现这一点
在我可能重新发明轮子之前,对于普通的Jackson注释和/或类,这可能吗
如果没有,我计划做如下的事情(注意:为了简化这个问题,我省略了很多配置选项和性能优化,这些对于核心功能来说是不必要的,但我会在核心工作后添加它们;为了简洁起见,我偶尔也会省略可见性修饰符等):
value
:
@Target({FIELD, METHOD})
@Retention(RUNTIME)
public @interface JsonApplyView {
Class<?> value();
}
ViewApplyingSerializer
将在其构造函数中保存以下属性:
final JsonSerializer<?> delegate;
final Class<?> appliedView;
其中serializerprovidercopy(serializerproviderp,类appliedView)
返回其\u serializationView=appliedView
p
:
delegate.serialize(o, g, copy(p, appliedView));
delegate.serialize(o, g, wrap(p, appliedView));
其中,SerializerProvider wrap(SerializerProvider p,类appliedView)
返回一个围绕p
的包装,其的
,getSerializationView()
返回appliedView
ObjectWriter
ow.writeValue(g, o);
其中,ow
以某种方式获得我想复制
SerializerProvider
是最好的,但是我发现复制SerializerProvider
并更改其活动视图的唯一方法需要传入SerializerFactory
,而我发现获得SerializerFactory
的唯一方法是构造一个新的,或者从ObjectMapper
获取一个。我更愿意使用当前SerializerProvider
中的\u serializerFactory
尽可能地模拟它,但该字段受到保护,我还没有找到任何getter。复制或包装序列化提供者
以使其具有不同的视图类
,最简单的方法是什么?很久以前就有人问过这个问题,但我也在寻找类似的方法。我认为如果杰克逊能够自己支持这一点就太好了,因为在我看来这是一个非常常见的案例
例如,假设您有一个视图层次结构,其中DetailView(高细节)继承自SummaryView(低细节),以及两个具有子-父关系的对象。使用活动的DetailView序列化子对象时,可能需要添加其父对象的摘要,而不一定要添加其所有详细信息。。。然后,您需要从DetailedView切换到SummaryView
无论如何,无需再次解释您已经知道的显而易见的事实,我最后做的是修改BeanSerializer,因为只有在序列化Bean时才会发生JsonView注释
@Override
public JsonSerializer<?> modifySerializer(SerializationConfig config, BeanDescription beanDesc, JsonSerializer<?> serializer) {
return new JsonViewOverrideSerializer(serializer);
}
最后,这里是一个棘手的部分,您需要覆盖SerializerProvider
对象。我也没有找到任何优雅的方法来实现这一点,因此我最终通过从JsonGenerator编解码器
ObjectMapper`检索SerializerFactory,创建了一个新的SerializerProvider'实例(我也是,我更愿意从被覆盖的提供者那里检索它,但是……太糟糕了,我没有办法访问它)
@Override
public JsonSerializer<?> modifySerializer(SerializationConfig config, BeanDescription beanDesc, JsonSerializer<?> serializer) {
return new JsonViewOverrideSerializer(serializer);
}
@Override
public JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property) throws JsonMappingException {
JsonSerializer<?> serializer = this.beanSerializer;
if (serializer instanceof ContextualSerializer) {
serializer = ((ContextualSerializer) serializer).createContextual(prov, property);
}
if (property != null) {
ApplyJsonView applyJsonView = property.getAnnotation(ApplyJsonView.class);
if (applyJsonView != null) {
Class<?> jsonView = applyJsonView.value();
serializer = new JsonViewOverrideSerializer(serializer, jsonView);
}
}
return serializer;
}
public SerializerProvider overrideProvider(Class<?> overrideView, JsonGenerator gen, SerializerProvider provider) {
return ((DefaultSerializerProvider) provider).createInstance(provider.getConfig().withView(overrideView), ((ObjectMapper) gen.getCodec()).getSerializerFactory(););
});
}
@Override
public void serialize(Object value, JsonGenerator gen, SerializerProvider provider) throws IOException {
SerializerProvider effectiveProvider = provider;
if (provider.getActiveView() != null && overrideView != provider.getActiveView()) {
effectiveProvider = overrideProvider(overrideView, gen, provider);
}
beanSerializer.serialize(value, gen, effectiveProvider);
}