I want to conditionally serialize a field. I figured out how to conditionally ignore a field with
JavaScript
x
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
JavaScript
@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
JavaScript
{"field1":"field1"}
Field2 is correctly ignored. But what I really want is
JavaScript
{"field1":"field1", "field2": "<***redacted***>"}
I have another annotation, @MaskSensitiveData
JavaScript
@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.
JavaScript
public class NologIntrospector extends JacksonAnnotationIntrospector {
@Override
public Object findSerializer(Annotated ann){
if (ann.hasAnnotation(NoLog.class)) {
return MaskSensitiveDataSerializer.class;
}
return super.findSerializer(ann);
}
}