自定义BeanPropertyFilter - 仅序列化字符串的一部分

时间:2014-10-08 06:49:44

标签: java json serialization jackson java-custom-serialization

我迫切需要帮助。我目前正在对Content API中的资源进行一些安全限制,我需要这样做:包含属性,截断属性(如果它们是String.class)或从序列化对象中删除属性,基于SecurityContext。

我使用Jackson作为我的json序列化程序,并选择使用BeanPropertyFilter来检查是否应该序列化每个属性。

现在删除和包含选项非常简单,无论是否序列化bean。

但截断选项有点糟糕。所以,到目前为止,我已经完成了关于财产序列化的事情。

@Override
public void serializeAsField(Object bean, JsonGenerator jgen, SerializerProvider provider, BeanPropertyWriter writer) throws Exception {
    switch (determineFilterAction(writer)) {
        case INCLUDE_UNMODIFIED:
            writer.serializeAsField(bean, jgen, provider);
            break;
        case INCLUDE_TRUNCATED:
            Object value = writer.get(bean);
            if (!(value instanceof String)) {
                throw new UnsupportedOperationException("Annotation indicates truncate on " + writer.toString() + " which is not a string, but a " + value.getClass().getSimpleName() + " and is unsupported");
            }
            JsonSerializer oldSerialzer= writer.getSerializer();
            writer.assignSerializer(new TruncateStringJsonSerializer());
            writer.serializeAsField(bean, jgen, provider);
            writer.assignSerializer(oldSerialzer);
            break;
        case REMOVE:
            // do nothing
            break;
    }
}

问题是,BeanPropertyWriter.assignSerializer()方法中有一个保护程序,它不允许我为该属性切换新的自定义序列化程序。

有没有办法挂钩,修改bean值?或者我是否必须覆盖Factories和BeanPropertyWriter以覆盖assignSerializer()方法(以避免序列化程序保护)?

我不能用特殊的编写器注释我的属性,因为序列化的对象对SecurityContext一无所知,所以没有办法将securityContext注入自定义序列化器。

是否有任何方法可以使这个截断选项发生(不会让它过于hackish)?

提前致谢。

//最好的问候,马丁。

更新

根据StaxMan的回答,我已经将方法更新为这样,它似乎有效。至少我的所有测试都运行正常。将在开发应用程序服务器上进一步测试。

@Override
public void serializeAsField(Object bean, JsonGenerator jgen, SerializerProvider provider, BeanPropertyWriter writer) throws Exception {
    switch (determineFilterAction(writer)) {
        case INCLUDE_UNMODIFIED:
            writer.serializeAsField(bean, jgen, provider);
            break;
        case INCLUDE_TRUNCATED:
            Object value = writer.get(bean);
            if (!(value instanceof String)) {
                throw new UnsupportedOperationException("Annotation indicates truncate on " + writer.toString() + " which is not a string, but a " + value.getClass().getSimpleName() + " and is unsupported");
            }
            String valueString = (String) value;
            jgen.writeFieldName(writer.getName());
            jgen.writeString(StringUtils.abbreviate(valueString, MAX_LENGTH));
            break;
        case REMOVE:
            // do nothing
            break;
    }
}

1 个答案:

答案 0 :(得分:2)

不,甚至不要尝试调用assignSerializer:这在多线程环境中是一个坏主意 - 只有一个该序列化器的实例,即使你可以调用它,它也是在同时完成两个序列化的情况下,只会引起一个奇怪的例外。

但也许你应该考虑从不同的方向接近这个:既然你已经找到String值,为什么不直接使用JsonGenerator写截断值? 或者,如果您愿意,委托给写作的东西;但既然你在调用它,它就不一定是JsonSerializer或任何东西。