java - 使用 Spring 存储库时 @JsonView 失败并显示 'IllegalStateException Can not override serializer'

标签 java json spring jackson

我们正在使用一些 Spring (v4.1.3.RELEASE) 存储库,最近开始使用 @JsonView 来过滤系统中其他 Controller 的一些响应数据。 今天我们发现 Jackson 尝试交换序列化器,但由于使用 @JsonView 注释标记的属性的未知原因而失败。

调试使我们到达 BeanSerializerBase.resolve(..) = 行#333-#337,其中进行了分配,但稍后失败并出现异常“IllegalStateException Can not override serializer”。代码中还引用了 [JACKSON-364]。

删除所有 JsonView 注释将其修复为解决方法。

我们仍在尝试调试并找出其根本原因,但任何提示都将不胜感激。

谢谢!

最佳答案

我们可以在源代码中看到

com.fasterxml.jackson.databind.ser.BeanPropertyWriter

    /**
     * Method called to assign value serializer for property
     * 
     * @since 2.0
     */
    public void assignSerializer(JsonSerializer<Object> ser)
    {
        // may need to disable check in future?
        if (_serializer != null && _serializer != ser) {
            throw new IllegalStateException("Can not override serializer");
        }
        _serializer = ser;
    }

因此我们无法使用此编写器类动态更改序列化器。

为了隐藏这个问题,我们可以使用(例如)

    public class ExtendBeanPropertyWriter extends BeanPropertyWriter {

        // constructors

        @Override
        public BeanPropertyWriter unwrappingWriter(NameTransformer unwrapper) {
            return new ExtendUnwrappingBeanPropertyWriter(this, unwrapper);
        }

        @Override
        public void assignSerializer(JsonSerializer<Object> ser) {
            _serializer = ser;
        }

    }

我们必须记住 UnwrappedBeanPropertyWriter

    public class ExtendUnwrappingBeanPropertyWriter extends UnwrappingBeanPropertyWriter {


        // constructors

        @Override
        public void assignSerializer(JsonSerializer<Object> ser) {
            _serializer = ser;
        }

    }

然后我们可以扩展 BeanSerializerModifier 方法 -changeProperties,将 writer 的类更改为我们的实现并避免此异常。

public class ExtendBeanSerializerModifier extends BeanSerializerModifier {

    private AnnotationIntrospector annotationIntrospector;

    // constructors

    @Override
    public List<BeanPropertyWriter> changeProperties(SerializationConfig config, BeanDescription beanDesc, List<BeanPropertyWriter> beanProperties) {

        annotationIntrospector = null == config ? null : config.getAnnotationIntrospector();
        List<BeanPropertyWriter> result = new ArrayList<BeanPropertyWriter>();
        for (BeanPropertyWriter beanPropertyWriter : beanProperties) {
            BeanPropertyWriter bpw = beanPropertyWriter;
            // we can get views from bpw.getViews(); active view from config.getActiveView();
            // we also can use own annotations, for example - beanDesc.getBeanClass().getAnnotation(SomeClass.class);
            result.add(getExtendBPW(bpw));
        }
        return result;
    }

    public BeanPropertyWriter getExtendBPW(BeanPropertyWriter bpw) {
        BeanPropertyWriter writer = new ExtendBeanPropertyWriter(bpw);
        if (null != annotationIntrospector) {
            NameTransformer unwrapper = annotationIntrospector.findUnwrappingNameTransformer(bpw.getMember());
            if (null != unwrapper) {
                writer = writer.unwrappingWriter(unwrapper);
            }
        }
        return writer;
    }

}

即使在那之后,您也可能会遇到 JsonView 问题。 您可能还需要添加自己的 HttpMessageConverter 和/或方法拦截器(您可以在互联网上找到示例)。

关于java - 使用 Spring 存储库时 @JsonView 失败并显示 'IllegalStateException Can not override serializer',我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31456112/

相关文章:

java - visual c++ 将 java 类作为进程运行

java - 如何只运行 2 次 do-while 循环?

java - 将 Allure 报告保存为 PDF 和电子邮件

xml - JSONX 到 JSON 转换

java - 多个@ElementCollection映射到同一个表的不同列

java - 列表值对 BaseAdapter 类不可见

javascript - JavaScript 的 JSON stringify 独立函数

python - 有没有办法让 Pyramid json 渲染器输出格式化的、 pretty-print 输出?

java - Spring Boot 和上下文路径

java - Spring 应用程序的混淆值得尝试吗?