How to exclude super class properties using Jackson

Viewed 961

I have a class:

public class User extends Body {
    private Integer userId;
    private String userName;
    private String emailId;

    //getters and setters
}

I want to exclude Body class properties with Jackson mapper because I get an error.

ObjectMapper mapper = new ObjectMapper();
User user = new User;
String jsonString = mapper.writeValueAsString(user);

How I can convert object to JSON with excluding all extended or implementation class? I need convert only User class without Body

My super class has many public method like this:

public final Enumeration method(String email) {
    throw new RuntimeException("Error");
}

public final Object method(String name) {
    throw new RuntimeException("Error");
}
1 Answers

1. Using @JsonView annotation

Jackson library has @JsonView annotation which allows to provide different views of the serialized class.

You need to create a class describing different views like this:

public class Views {
    public interface Base {}  // view of Base class properties
    public interface Child {} // view of Child class properties (i.e. User)
}

Then you mark up the fields/getters in the base Body class with @JsonView(Views.Base.class):

public class Body {
    @JsonView(Views.Base.class)
    private int foo;

    @JsonView(Views.Base.class)
    public String getBar() {
        return "bar";
    }

    // other getters/setters
}

The User class can be marked at class level:

@JsonView(Views.Child.class)
public class User extends Body {
    private Integer userId;
    private String userName;
    private String email;

    // getters/setters
}

And when serializing with ObjectMapper you set its writer up to use specific view writerWithView:

ObjectMapper mapper = new ObjectMapper();//

User user = new User(1, "Jack", "jack@company.com");

String json = mapper.writerWithView(Views.Child.class).writeValueAsString(user);

System.out.println("custom view: " + json);  
System.out.println("full   view: " + mapper.writeValueAsString(user));

Output:

custom view: {"userId":1,"name":"Jack","email":"jack@company.com"}
full   view: {"foo":0,"userId":1,"name":"Jack","email":"jack@company.com","bar":"bar"}

2. Using @JsonIgnoreProperties annotation

It is also possible to customize the view of the child class by ignoring its parent class' properties:

@JsonIgnoreProperties({"foo", "bar"})
public class User extends Body {
    private Integer userId;
    private String name;
    private String email;
}

Then there's no need to configure the writer ObjectMapper instance:

System.out.println("base class fields ignored: " + mapper.writeValueAsString(user));

Output:

base class fields ignored: {"userId":1,"name":"Jack","email":"jack@company.com"}

3. Configure ObjectMapper to set custom JacksonAnnotationIntrospector

It is also possible to configure the ObjectMapper instance to set a custom annotation introspector to completely ignore properties belonging to the parent Body class:

// imports for Jackson v.2.x
// import com.fasterxml.jackson.databind.introspect.AnnotatedMember;
// import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector;
// imports for Jackson v.1.9
import org.codehaus.jackson.map.introspect.AnnotatedMember;
import org.codehaus.jackson.map.introspect.JacksonAnnotationIntrospector;

class IgnoreBodyClassIntrospector extends JacksonAnnotationIntrospector {
    @Override
    public boolean hasIgnoreMarker(final AnnotatedMember member) {
        return member.getDeclaringClass() == Body.class || super.hasIgnoreMarker(member);
    }
}

Configure ObjectMapper and serialize User without any code changes to Body and User:

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

User user = new User(3, "Nobody", "nobody@company.com");

System.out.println("no base class fields: " + mapper.writeValueAsString(user));

Output:

no base class fields: {"userId":3,"name":"Nobody","email":"nobody@company.com"}
Related