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

标签 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 才能重写 allocateSerializer() 方法(以避免序列化器防护)?

我不能只用特殊的编写器注释我的属性,因为序列化对象不知道有关 SecurityContext 的任何信息,因此无法将 securityContext 注入(inject)自定义序列化程序。

有没有什么办法可以让这个截断选项发生(又不会让它太黑客化)?

提前致谢。

//最诚挚的问候,马丁。

更新

根据 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;
    }
}

最佳答案

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

但也许您应该考虑从不同的方向处理这个问题:既然您已经找到了 String 值,为什么不直接使用 JsonGenerator 写入截断的值呢? 或者,如果您愿意,可以委托(delegate)给进行写入操作的人员;但既然你正在调用它,它就不必是 JsonSerializer 或任何东西。

关于java - 自定义 BeanPropertyFilter - 仅序列化字符串的一部分,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26250755/

相关文章:

javascript - 如何使用 d3 从嵌套的 JSON 数组中调用数据?

arrays - 如何在 UI 中显示解析后的 JSON 数据?

mysql - 你能在 MySql 中将行转换为 json 吗?

java - Jetty URL 重写/重定向去除查询字符串

java - 层列表形状 + 位图顶部有填充

javascript - ASP.NET MVC4 : On text changed, 执行ajax请求,然后返回json结果并更新模型而不重新加载页面

c# - 当对象实现 Equals 时,Newtonsoft.Json 序列化表现得很奇怪

jquery - 序列化空数组输入

java - 设置布局宽度占屏幕总宽度的百分比

java - 如何以编程方式将图像下载到 iPad?