Динамически предотвращать сериализацию определенных полей с помощью PropertyFilter Джексона - PullRequest
0 голосов
/ 26 мая 2018

Мне нужно иметь возможность предотвратить сериализацию определенных полей объектов, в первую очередь в зависимости от их типа.Например, рассмотрим следующий объект:

class MyPojo {
    private int myInt;
    private boolean myBoolean;

    // getters, setters, etc.
}

Я хотел бы иметь возможность при сериализации не сериализовать логическое поле, если оно ложно.Или не сериализуйте int, если он равен нулю.По сути, не сериализуйте какое-либо конкретное поле на основе какого-либо свойства его типа или определенного значения.

Мне известны JsonSerializer, которые я использовал для частичного решения своей проблемы, но выбрать невозможноне сериализовать поле в JsonSerializer .

. Самое близкое, что я получил, - это реализация моего собственного PropertyFilter и применение его к моему объекту через @JsonFilter:

public class XmlPropertyFilter implements PropertyFilter {
    @Override
    public void serializeAsField(Object pojo, JsonGenerator gen, SerializerProvider prov, PropertyWriter writer) throws Exception {
        JavaType type = writer.getType();

        if (writer instanceof BeanPropertyWriter) {
            BeanPropertyWriter bWriter = (BeanPropertyWriter) writer;

            String fieldName = bWriter.getSerializedName().getValue();
            Field f = pojo.getClass().getDeclaredField(fieldName);
            f.setAccessible(true);
            Object value = f.get(pojo);

            if (!type.isTypeOrSubTypeOf(int.class) && value != null) {
                // Serialize everything that isn't an int and doesn't have a null value
                prov.defaultSerializeField(fieldName, value, gen);
            } else if (type.isTypeOrSubTypeOf(int.class)) {
                // Only serialize ints if the value isn't 0
                if (value != 0) prov.defaultSerializeField(fieldName, value, gen);
            }
        }

    }

    // ...
}

Это именно то, что я хочу, за исключением того, что у него есть неприятный побочный эффект, связанный с нарушением переноса (например, сериализация списка).Согласно документации @JsonFilter, допустимо применять фильтр к полю, а не ко всему классу, что было бы замечательно, но я попробовал это и не могу заставить его работать.

1 Ответ

0 голосов
/ 26 мая 2018

Я нашел решение, и это именно то, что я искал.Секрет в методе BeanPropertyWriter#serializeAsOmittedField(Object, JsonGenerator, SerializerProvider).Это делает именно то, что невозможно сделать внутри JsonSerializer - он полностью удаляет поле из вывода.

Вот пример этого DynamicPropertyFilter:

public class DynamicPropertyFilter implements PropertyFilter {
    public void serializeAsField(Object pojo, JsonGenerator jgen, SerializerProvider prov, PropertyWriter writer) throws Exception {
        if (writer instanceof BeanPropertyWriter) {
            BeanPropertyWriter bWriter = (BeanPropertyWriter) writer;

            String fieldName = bWriter.getFullName().getSimpleName();
            Field field = pojo.getClass().getDeclaredField(fieldName);
            field.setAccessible(true);
            Object object = field.get(pojo);

            if (Double.class.isInstance(object) && (double) object == 0.0) {
                // Remove all double fields that are equal to 0.0
                bWriter.serializeAsOmittedField(pojo, jgen, prov);
                return;
            } else if (Boolean.class.isInstance(object)) {
                // Change all boolean fields to 1 and 0 instead of true and false
                prov.defaultSerializeField(fieldName, (boolean) object ? 1 : 0, jgen);
                return;
            }
        }

        // Serialize field as normal if property is not filtered
        writer.serializeAsField(pojo, jgen, prov);
    }

    public void serializeAsElement(Object elementValue, JsonGenerator jgen, SerializerProvider prov, PropertyWriter writer) throws Exception {
        writer.serializeAsField(elementValue, jgen, prov);
    }

    public void depositSchemaProperty(PropertyWriter writer, JsonObjectFormatVisitor objectVisitor, SerializerProvider provider) throws JsonMappingException {
        writer.depositSchemaProperty(objectVisitor, provider);
    }

    @Deprecated
    public void depositSchemaProperty(PropertyWriter writer, ObjectNode propertiesNode, SerializerProvider provider) throws JsonMappingException {
        writer.depositSchemaProperty(propertiesNode, provider);
    }
}

Не только я могу фильтровать поля, что в первую очередь мне и нужно, но я также могу изменять их (как видно из логического примера),Это исключает необходимость использования PropertyFilter и JsonSerializer.

...