Dynamic serialization using Jackson – removing fields with specific annotations

Tags: , , ,

Went down a path of creating an annotation that would dynamic determine whether a field should be serialized or not.

The annotation’s implementation is as follows:

@JsonSerialize(using = HiddenFieldSerializer.class)
@Target(value = ElementType.FIELD)
public @interface Hidden {

Now the code for the Serializer:

public class HiddenFieldSerializer
        extends StdSerializer<String>
        implements ContextualSerializer {

    public HiddenFieldSerializer() {

    public void serialize(String value,
                          JsonGenerator jgen,
                          SerializerProvider provider) {
        try {
        } catch (IOException e) {

    public JsonSerializer<?> createContextual(SerializerProvider prov,
                                              BeanProperty property) {
        return shouldHide() ?
                new HiddenFieldSerializer() : new StringSerializer();

    public boolean shouldHide() {
        /* Simplifying this */
        return Boolean.TRUE;

A little bit of code to show how it works:

public class Test {
    static final ObjectMapper mapper = new ObjectMapper()

    static class User {
        String username;

        String pin;

    public static void main(String... args)
            throws JsonProcessingException {

        final POC.User u = new POC.User();
        u.username = "harry_potter";
        u.pin = "1298";


And the output is as follows:


How do I get the field pin to be removed from the serialization instead of it being null? Obviously setting the mapper’s properties was of very little user in such a context. Any suggestions? Thoughts? Maybe the whole thing is a bad idea?

Ideally I should be able to see the following:



It’s not clear whether you want to ignore a given property statically or dynamically. Anyways, looks like you have over-engineered it.

First of all, I want to make sure that you came across @JsonIgnore before. If it doesn’t suit your needs, you could define your custom ignore annotation as following:

public @interface Hidden {


Then pick the approach that best suit your needs:

Approach #1

Extend JacksonAnnotationIntrospector and override the method that checks for the ignore marker:

public class CustomAnnotationIntrospector extends JacksonAnnotationIntrospector {

    public boolean hasIgnoreMarker(AnnotatedMember m) {
        return super.hasIgnoreMarker(m) || m.hasAnnotation(Hidden.class);

Configure ObjectMapper to use your annotation introspector:

ObjectMapper mapper = new ObjectMapper();
mapper.setAnnotationIntrospector(new CustomAnnotationIntrospector());

The annotation introspection occurs only once per class so you can not dynamically change the criteria you use (if any). A similar example can be seen in this answer.

Approach #2

Extend BeanSerializerModifier to modify the properties that will be serialized:

public class CustomBeanSerializerModifier extends BeanSerializerModifier {

    public List<BeanPropertyWriter> changeProperties(SerializationConfig config, 
            BeanDescription beanDesc, List<BeanPropertyWriter> beanProperties) {

        return beanProperties.stream()
                .filter(property -> property.getAnnotation(Hidden.class) == null)

Then add it to a Module and register it to your ObjectMapper:

ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new SimpleModule() {

    public void setupModule(SetupContext context) {
        context.addBeanSerializerModifier(new CustomBeanSerializerModifier());

This approach allows you to ignore properties dynamically.

Source: stackoverflow