Как сделать динамическую фильтрацию на основе исключения с аннотациями? - PullRequest
0 голосов
/ 07 января 2019

Я хочу разработать компонент, позволяющий фильтровать поля DTO на основе алгоритма исключения поля объекта, подлежащего сериализации (JSON). Основываясь на имени, упомянутом в аннотации Джексона «@JsonProperty», если оно присутствует, в противном случае используйте имя самого поля (отображение без аннотации).

Пожалуйста, как сделать динамическую фильтрацию на основе исключения с аннотациями? Есть ли полезные ресурсы (код, tutos, ...)?

Класс 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;
    }

}

1 Ответ

0 голосов
/ 11 января 2019

Есть несколько проблем с вашим кодом:

  • Вы не передаете объект 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}
...