Custom Annotation Discovery using Jackson

Last couple of weeks I was working on a project which required processing the annotations on a complex object(containing Primitives and other complex objects), and analyze the annotation even inside the fields(if they are not Values, and instead complex objects).

I started thinking about processing the annotation CustomAnnotation.

@Target({ElementType.PARAMETER, ElementType.FIELD})
public @interface CustomAnnotation {
String value1();
Integer value2();

I was thinking to do something on following lines:

1. Check the fields of object for CustomAnnotation.
2. If the field is of primitive type, save the field value along with the annotation on it.
3. If the field is in itself a complex object obj, go inside it and start from step 1 for every field in obj.

On a single look, it seemed fine to me, but then I saw the problems in this approach:

  1. It doesn’t handle Arrays, Map. Moreover adding handling for these will be too much code followed by debugging and unexpected issues in production.
  2. The code will always check for annotations at runtime, which is bad.

Then I thought for a while, and it popped up in my mind that Jackson does something very similar. Not exactly similar but Jackson does go inside objects and find the annotations on it to serialize or deserialize the object.

Then I decided to go straight into code of Jackson to use some of its code for processing. That would be much optimized and probably error free(Thanks to years of development).

After a couple of hours into the code base and I finally reached the portion of code responsible for reading annotations such as JsonProperty, JsonGetter, JsonSetter, etc which is JacksonAnnotationIntrospector. And thanks to the development team, we could replace this class in the initialization of ObjectMapper.

So here is how I did that, I extended the class JacksonAnnotationIntrospector , and overrides a couple of methods: findNameForSerialization and hasIgnoreMarker . Code for the above overriding implementation is as below:

@Override // Method to get the key name
public PropertyName findNameForSerialization(Annotated a)
CustomAnnotation an = _findAnnotation(a, CustomAnnotation.class);
if(an != null) {
return PropertyName.construct(serializeCustomAnnotation(an));
return null; // Not serializing fields not marked with AuditableParameter
@Override //Ignoring all fields which doesn't have  CustomAnnotation
public boolean hasIgnoreMarker(AnnotatedMember m) {
CustomAnnotation an = _findAnnotation(a, CustomAnnotation.class);
if(an == null) {
return true;
return false;
String serializeCustomAnnotation(CustomAnnotation an) {
return an.value1() + " $ " + an.value2();

The serializeCustomAnnotation method is used because Jackson only handles String as key, and not an Object .

Using Jackson along with extension of JacksonAnnotationIntrospector , we can easily get the root node of the tree where each key is an encoding of the CustomAnnotation . By traversing the tree you can get the key which is encoding of CustomAnnotation (we decode it to make an object out it), and value as runtime value of object.

So here, I reduced the code I need to write by almost 90%, and thereby reducing the debugging time by probably the same factor. Also it’s much optimized as Jackson does the check for annotation once per model.

Hope it helped. :-)