【问题标题】:How to do dynamic filtering based on exclusion with annotations?如何使用注释进行基于排除的动态过滤?
【发布时间】:2019-01-07 10:57:43
【问题描述】:

我想开发一个组件,该组件允许基于要序列化的对象字段的排除算法 (JSON) 过滤 DTO 的字段。基于 Jackson 注释“@JsonProperty”中提到的名称(如果存在),否则使用字段本身的名称(不带注释的映射)。

请问,如何使用注释进行基于排除的动态过滤?是否有一些有用的资源(代码、教程、...)?

JacksonFieldFilter 类

public class JacksonFieldFilter {

    public <T> T filter(T input, List<String> toExclude, Function<Object, Object> fun) throws IllegalArgumentException, IllegalAccessException {

        Field[] fields = input.getClass().getFields();
        for (Field field : fields) {

            // check is not elementary type.
            // if not ==> get its annotation
            Annotation[] annaotations = field.getAnnotations();

            /// Filter on Jakson annotation only with name == JSonProperty
            Annotation ja = getJakson(annaotations);

            /// get annotation value as String ==> annotationNameValue.
            String annotationNameValue = null;

            if (toExclude.contains(annotationNameValue)) {
                /// found the name in excluded values list
                Object prev = field.get(input);
                field.set(input, fun.apply(prev));
            }

        }

        return input;
    }

    Annotation getJakson(Annotation[] annaotations) {
        for (Annotation annotation : annaotations) {
            if (annotation.annotationType().isAssignableFrom(JsonProperty.class)) {
                return annotation;
            }
        }
        return null;
    }

    // Test 

    public static void main(String[] args) throws IllegalArgumentException, IllegalAccessException {
        JacksonFieldFilter filter = new JacksonFieldFilter();
        Item item = new Item();
        item.setField1("London");
        item.setField2("Paris");

        Item clone = null; // item.

        clone = filter.filter(clone, Arrays.asList(new String[] { "field_1" }), p -> {
            System.err.println("Erasing " + p);
            return null;
        });

        // OUTPUT ==> {"field_2":"Paris"}
        System.out.println(clone); 
    }

}

类项

public class Item {
    @JsonProperty("field_1")
    private String field1;
    @JsonProperty("field_2")
    private String field2;

    public String getField1() {
        return field1;
    }

    public void setField1(String field1) {
        this.field1 = field1;
    }

    public String getField2() {
        return field2;
    }

    public void setField2(String field2) {
        this.field2 = field2;
    }

}

【问题讨论】:

标签: java jackson objectmapper


【解决方案1】:

您的代码存在一些问题:

  • 您没有将item 对象传递给过滤函数,因此您无法复制clone 中的字段值
  • Item 类中的字段是私有的,因此您必须使用 getClass().getDeclaredFields() 和 setAccessible() 来访问/写入它们。

试试下面的代码:

public static class JacksonFieldFilter {

    public <T> T filter(T src, T dest, Collection<String> toExclude, Function<String, Void> callback)
        throws IllegalArgumentException, IllegalAccessException {

        Field[] fields = src.getClass().getDeclaredFields();
        for (Field field : fields) {
            JsonProperty property = field.getAnnotation(JsonProperty.class);
            if (property != null) {
                String value = property.value();
                if (toExclude.contains(value)) {
                    callback.apply(value);
                } else {
                    // Write the value from "src" to "dest"
                    field.setAccessible(true); // Without this we can not write into a private field
                    field.set(dest, field.get(src));
                }
            }
        }
        return dest;
    }
}

// ...
public static void main(String[] args) throws Exception {
    Item item = new Item();
    item.setField1("London");
    item.setField2("Paris");

    Item clone = new JacksonFieldFilter().filter(item, new Item(), Arrays.asList(new String[]{"field_1"}), (f) -> {
        System.out.println("Erasing " + f);
        return null;
    });
    System.out.println(clone);
}

输出:

Erasing field_1
Item{field1=null, field2=Paris}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-11-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-31
    • 1970-01-01
    • 2018-02-24
    相关资源
    最近更新 更多