Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/318.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 更改属性的活动视图_Java_Json_Jackson - Fatal编程技术网

Java 更改属性的活动视图

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注释和/或类,这可能吗 如果没有,我计划做如下的事情(注意:为了简化这个问题,我省略了很多配置选项和性能优化,这些

使用Jackson,我希望能够在序列化属性时更改活动视图

因此,如果我的应用程序使用3个视图A、B和C,我可能希望类型T的属性p始终使用视图A进行序列化,而不管活动视图
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);
    }