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);
}
}