yves amsellem
yves amsellem

Reputation: 7244

Disable Jackson mapper for a particular annotation

With Jackson, it's easy to disable all annotations for a given ObjectMapper. Is there a way to only disable one given annotation?

// disable all
ObjectMapper mapper = new ObjectMapper()
mapper.disable(MapperFeature.USE_ANNOTATIONS);

// disable one?
ObjectMapper mapper = new ObjectMapper()
mapper.disable(@JsonIgnore);

Using @JacksonAnnotationsInside, I've defined a custom Jackson annotation and I only want it to be used in certain circumstances.

Upvotes: 7

Views: 10878

Answers (4)

Tom Grushka
Tom Grushka

Reputation: 549

Here is a simpler way (August 2022) to do it in Kotlin (you can translate to Java if you really want to):

(I use this in a Ktor/KMongo project to prevent Transient attributes from being persisted because KMongo requires @JsonIgnore, which then also prevents my other mappers from serializing those properties!)

@Target(PROPERTY_GETTER)
annotation class Transient

private val TransientIntrospector: JacksonAnnotationIntrospector = object : JacksonAnnotationIntrospector() {
    override fun hasIgnoreMarker(m: AnnotatedMember): Boolean =
        m.allAnnotations.has(Transient::class.java) || super.hasIgnoreMarker(m)
}

private class IgnoreTransientModule : SimpleModule() {
    override fun setupModule(context: SetupContext) {
        super.setupModule(context)
        context.appendAnnotationIntrospector(TransientIntrospector)
    }
}

// Just register the module in your `ObjectMapper` instance:
val ignoreTransientMapper = with(ObjectMapper()) {
    registerModule(IgnoreTransientModule())
}

// And here is how to use it:
data class Customer(
    val id: String? = null,
    val firstName: String,
    val lastName: String,
) {
    @get:Transient
    val fullName: String
        get() = "$firstName $lastName"
}

Upvotes: 0

Oleg Kuts
Oleg Kuts

Reputation: 829

This solution worked for me. Check this for more info

 private static final JacksonAnnotationIntrospector IGNORE_ENUM_ALIAS_ANNOTATIONS = new JacksonAnnotationIntrospector() {

    @Override
    protected <A extends Annotation> A _findAnnotation(final Annotated annotated, final Class<A> annoClass) {
        if (!annotated.hasAnnotation(JsonEnumAliasSerializer.class)) {
            return super._findAnnotation(annotated, annoClass);
        }
        return null;
    }
};

And my custom annotation:

@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotationsInside
@JsonSerialize(using = JsonEnumSerializer.class)
public @interface JsonEnumAliasSerializer {
}

And ObjectMapper:

    final ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.setAnnotationIntrospector(IGNORE_ENUM_ALIAS_ANNOTATIONS);

Upvotes: 1

hasan
hasan

Reputation: 1114

I think it's a better idea to override findPropertiesToIgnore method like this:

    JacksonAnnotationIntrospector ignoreJsonTypeInfoIntrospector = new JacksonAnnotationIntrospector() {
        @Override
        public String[] findPropertiesToIgnore(AnnotatedClass ac) {
            ArrayList<String> ret = new ArrayList<String>();
            for (Method m : ac.getRawType().getMethods()) {
                if(ReflectionUtils.isGetter(m)){
                    if(m.getAnnotation(Transient.class) != null)
                        ret.add(ReflectionUtils.getPropertyName(m));

                }
            };
            return ret.toArray(new String[]{});
        }
    };
    objectMapper = new ObjectMapper();
    objectMapper.setAnnotationIntrospector(ignoreJsonTypeInfoIntrospector);

Upvotes: 0

755
755

Reputation: 3091

This the best I've come across. I think I saw it on the Jackson user group forums somewhere.

Essentially it makes a custom annotation introspector, which returns null if it sees that it has a specific annotation (in this case JsonTypeInfo)

JacksonAnnotationIntrospector ignoreJsonTypeInfoIntrospector = new JacksonAnnotationIntrospector() {
            @Override
            protected TypeResolverBuilder<?> _findTypeResolver(
                    MapperConfig<?> config, Annotated ann, JavaType baseType) {
                if (!ann.hasAnnotation(JsonTypeInfo.class)) {
                    return super._findTypeResolver(config, ann, baseType);
                }
                return null;
            }
        };

        mapper.setAnnotationIntrospector(ignoreJsonTypeInfoIntrospector);

Upvotes: 2

Related Questions