杰克逊动态过滤反序列化过程中的属性

Mar*_*rio 9 java json filtering jackson deserialization

我有一个REST WS来更新一个bean对象,它接收一个JSON字符串作为输入.

ABean entity = svc.findEntity(...);
objectMapper.readerForUpdating(entity).readValue(json);
[...]
svc.save(entity);
Run Code Online (Sandbox Code Playgroud)

ABean是一个包含其他对象的复杂类型,例如:

class ABean {
    public BBean b;
    public CBean c;

    public String d;
}
Run Code Online (Sandbox Code Playgroud)

svc.save(...)将保存bean和嵌入对象.

出于安全原因,我想过滤掉一些可以通过JSON字符串更新的属性,但我想动态地执行此操作,以便对于每个WS(或用户角色),我可以决定阻止更新哪些属性(所以我不能简单地使用杰克逊观点)

总而言之,有什么方法可以在JSON反序列化期间动态过滤掉属性?

小智 7

另一种方法是使用BeanDeserializerModifier:

private static class BeanDeserializerModifierForIgnorables extends BeanDeserializerModifier {

        private java.lang.Class<?> type;
        private List<String> ignorables;

        public BeanDeserializerModifierForIgnorables(java.lang.Class clazz, String... properties) {
            ignorables = new ArrayList<>();
            for(String property : properties) {
                ignorables.add(property);
            }
            this.type = clazz;
        }

        @Override
        public BeanDeserializerBuilder updateBuilder(
                DeserializationConfig config, BeanDescription beanDesc,
                BeanDeserializerBuilder builder) {
            if(!type.equals(beanDesc.getBeanClass())) {
                return builder;
            }

            for(String ignorable : ignorables) {
                builder.addIgnorable(ignorable);                
            }

            return builder;
        }

        @Override
        public List<BeanPropertyDefinition> updateProperties(
                DeserializationConfig config, BeanDescription beanDesc,
                List<BeanPropertyDefinition> propDefs) {
            if(!type.equals(beanDesc.getBeanClass())) {
                return propDefs;
            }

            List<BeanPropertyDefinition> newPropDefs = new ArrayList<>();
            for(BeanPropertyDefinition propDef : propDefs) {
                if(!ignorables.contains(propDef.getName())) {
                    newPropDefs.add(propDef);
                }
            }
            return newPropDefs;
        }
    }
Run Code Online (Sandbox Code Playgroud)

您可以使用以下命令将修改器注册到ObjectMapper:

BeanDeserializerModifier modifier = new BeanDeserializerModifierForIgnorables(YourType.class, "name");
DeserializerFactory dFactory = BeanDeserializerFactory.instance.withDeserializerModifier(modifier);
ObjectMapper mapper = new ObjectMapper(null, null, new DefaultDeserializationContext.Impl(dFactory));
Run Code Online (Sandbox Code Playgroud)

然后忽略定义的属性.如果使用@JsonAnySetter批注,则可以忽略updateBuilder方法.

问候,马丁