【问题标题】:Dynamically prevent certain fields from being serialized with Jackson's PropertyFilter动态防止某些字段被 Jackson 的 PropertyFilter 序列化
【发布时间】:2018-05-26 03:58:19
【问题描述】:

我需要能够防止对象的某些字段被序列化,主要是基于它们的类型。例如,考虑以下对象:

class MyPojo {
    private int myInt;
    private boolean myBoolean;

    // getters, setters, etc.
}

我希望能够在序列化时不序列化布尔字段,如果它是假的。或者如果它为零,则不序列化 int。基本上,不要根据其类型或特定值的任何属性来序列化任何特定字段。

我知道 JsonSerializers,我曾经用它来部分解决我的问题,但它是 impossible to choose not to serialize a field in a 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 文档,将过滤器应用于字段而不是整个类是有效的,这会很棒,但我已经尝试过了,但似乎无法让它工作。

【问题讨论】:

    标签: java serialization jackson jackson-dataformat-xml


    【解决方案1】:

    我找到了解决方案,这正是我所寻找的。秘密是方法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 的需求。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-10-29
      • 1970-01-01
      • 2021-02-19
      • 1970-01-01
      • 1970-01-01
      • 2015-01-19
      • 1970-01-01
      相关资源
      最近更新 更多