如何有条件地序列化一个字段

How to conditionally serialize a field

我想有条件地序列化一个字段。我想出了如何有条件地忽略带有

的字段
public class NologIntrospector extends JacksonAnnotationIntrospector {
    @Override
    public boolean hasIgnoreMarker(AnnotatedMember m) {
        boolean noLogOnClass = m.getDeclaringClass().getAnnotation(NoLog.class) != null;
        return m.hasAnnotation(NoLog.class) || super.hasIgnoreMarker(m) || noLogOnClass;
    }
}

但我真正想做的是编辑该字段。所以如果我有

@Getter
@Setter
@NoArgsConstructor
public class MyObject1 {
    public String field1 = "field1";
    @NoLog
    public String field2 = "field2";

    public static void main(String[] args) throws JsonProcessingException {
        final ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.setAnnotationIntrospector(new NologIntrospector());
        final MyObject1 myObject1 = new MyObject1();
        System.out.println(objectMapper.writeValueAsString(myObject1));
    }
}

我明白了

{"field1":"field1"}

Field2 被正确地忽略了。但我真正想要的是

{"field1":"field1", "field2": "<***redacted***>"}

我还有一个注释,@MaskSensitiveData

@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotationsInside
@JsonSerialize(using = MaskSensitiveDataSerializer.class)
public @interface MaskSensitiveData {
}

public class MaskSensitiveDataSerializer extends StdSerializer<Object> {

    protected MaskSensitiveDataSerializer() {
        this(null);
    }

    public MaskSensitiveDataSerializer(Class<Object> t) {
        super(t);
    }

    @Override
    public void serialize(Object value, JsonGenerator gen, SerializerProvider provider) throws IOException {
        if (!(value instanceof  String)) {
            throw new RuntimeException("MaskSensitiveData annotation is only valid for string");
        }
        gen.writeString("<*** redacted ***>");
    }
}

所以我想做的就是把它们结合起来。因此,如果一个字段具有特殊注释并且我正在使用我的内省器,那么我是否想编辑该字段。否则,该字段应该正常序列化。

而不是覆盖 NologIntrospector 中的方法 hasIgnoreMarker。您需要覆盖 findSerializer。 这样,当您的内省器启用时,将使用自定义序列化器,否则它将使用原始序列化器。

public class NologIntrospector extends JacksonAnnotationIntrospector {
    @Override
    public Object findSerializer(Annotated ann){
        if (ann.hasAnnotation(NoLog.class)) {
            return MaskSensitiveDataSerializer.class;
        }
        return super.findSerializer(ann);
    }
}