I want to conditionally serialize a field. I figured out how to conditionally ignore a field with
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; } }
But what I really want to do is to redact the field. So if I have
@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)); } }
I get
{"field1":"field1"}
Field2 is correctly ignored. But what I really want is
{"field1":"field1", "field2": "<***redacted***>"}
I have another annotation, @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 ***>"); } }
So what I want to do is combine them. So if a field has the special annotation and I am using my introspector, only then, do I want to redact the field. Otherwise, the field should be serialized normally.
Advertisement
Answer
Instead of overriding method hasIgnoreMarker
in NologIntrospector
. You need to override findSerializer
.
This way when your introspector is enabled the custom serializer will be used else it will use the original serializer.
public class NologIntrospector extends JacksonAnnotationIntrospector { @Override public Object findSerializer(Annotated ann){ if (ann.hasAnnotation(NoLog.class)) { return MaskSensitiveDataSerializer.class; } return super.findSerializer(ann); } }