Jackson JSON: difference between @JsonIgnore and @JsonIgnoreProperties annotations

Jackson has two different annotations to use when you want to exclude some class members from the JSON serialization and deserialization processes. These two annotations are @JsonIgnore and @JsonIgnoreProperties.
@JsonIgnoreProperties is an annotation at the class level and it expects that the properties to be excluded would be explicitly indicated in the form of a list of strings.
@JsonIgnore instead is a member-level or method-level annotation, which expects that the properties to be excluded are marked one by one. To completely exclude a member from the process of serialization and de-serialization it’s possibile to annotate the actual property or its setter or its getter. (This behavior is in force since version 1.9 of Jackson). It’s also possible to exclude properties in an asymmetrical way between serialization and deserialization, but we’ll see an example of this case in another post.

Now let’s see a concrete example of use of these annotations. We create a class MyTestClass with some properties and the related getters and setters and a simple test class in which we create an object of that class and then we perform its JSON serialization and deserialization.
We start with an example using the class as-is, without annotations which exclude certain properties.

import java.io.IOException;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;

class MyTestClass {

    private long id;
    private String name;
    private String notInterstingMember;
    private int anotherMember;
    private int forgetThisField;

    public long getId() {
        return this.id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public String getName() {
        return this.name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getNotInterstingMember() {
        return this.notInterstingMember;
    }

    public void setNotInterstingMember(String notInterstingMember) {
        this.notInterstingMember = notInterstingMember;
    }

    public int getAnotherMember() {
        return this.anotherMember;
    }

    public void setAnotherMember(int anotherMember) {
        this.anotherMember = anotherMember;
    }

    public int getForgetThisField() {
        return this.forgetThisField;
    }

    public void setForgetThisField(int forgetThisField) {
        this.forgetThisField = forgetThisField;
    }

    @Override
    public String toString() {
        return "MyTestClass [" + this.id + " , " +  this.name + ", " + this.notInterstingMember + ", " + this.anotherMember + ", " + this.forgetThisField + "]";
    }

}

public class JSONIgnorePropTest {

    public static void main(String[] args) {

        ObjectMapper mapper = new ObjectMapper();

        MyTestClass mtc = new MyTestClass();
        mtc.setId(1);
        mtc.setName("Test program");
        mtc.setNotInterstingMember("Don't care about this");
        mtc.setAnotherMember(100);
        mtc.setForgetThisField(-1);


        String s = null;
        try {
            s = mapper.writeValueAsString(mtc);
        }
        catch (JsonProcessingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        System.out.println(s);

        MyTestClass mtc2 = null;
        try {
            mtc2 = mapper.readValue(s, MyTestClass.class);
        }
        catch (JsonParseException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        catch (JsonMappingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        System.out.println(mtc2.toString());

    }
}

The result of this first run is the following, in which all the fields and their values are serialized and then “reconstructed” during deserialization.

{"id":1,"name":"Test program","notInterstingMember":"Don't care about this","anotherMember":100,"forgetThisField":-1}
MyTestClass [1 , Test program, Don't care about this, 100, -1]

Now suppose you want to exclude from the results of serialization and deserialization some of the class MyTestClass properties, for instance the “notInterstingMember” and “forgetThisField” properties. As first case we see how to achieve this with the @JsonIgnoreProperties annotation. To do that we have to change our MyTestClass class as follows:

@JsonIgnoreProperties({"notInterstingMember", "forgetThisField"})
class MyTestClass {

    private long id;
    private String name;
    private String notInterstingMember;
    private int anotherMember;
    private int forgetThisField;

	// REST OF THE CODE...
}

By running the program again, this time we get the following result:

{"id":1,"name":"Test program","anotherMember":100}
MyTestClass [1 , Test program, null, 100, 0]

As we can see, in the string produced by the serialization process are not present the values of the properties that we have indicated to exclude through the annotation. After the deserialization therefore, these properties assume the default value provided by their type, then “null” for the String property and 0 for the int property.

The same result can also be obtained using the other annotation, @JsonIgnore which, as mentioned, is not a “class-level” annotation but a “member-level” or “method-level” one. Let’s change again our example class as follows:

class MyTestClass {
	private long id;
	private String name;

	@JsonIgnore
	private String notInterstingMember;
	
	private int anotherMember;

	@JsonIgnore
	private int forgetThisField;

	// REST OF THE CODE
}

By running the program again we can see that the result is the same as in the previous case.

{"id":1,"name":"Test program","anotherMember":100}
MyTestClass [1 , Test program, null, 100, 0]

As we said at the beginning of the post, to accomplish this result using the @JsonIgnore annotation, it can be put directly on the instance member or on its getter or its setter. The application of the annotation in any of these 3 points, leads to the total exclusion of the property from both the serialization and de-serialization processes (this applies starting from Jackson 1.9; the version used in these examples is Jackson 2.4.3).
It’s possible to change this behavior and make it asymmetric, for example to exclude a property only from the deserialization using the @JsonIgnore annotation together with another annotation called @JsonProperty.

In the following example we annotate with @JsonIgnore the getter of the “notInterstingMember” property and the setter of the “forgetThisField” property (without annotate the property itself). How can we see the result is once again equal to those from previous examples.

import java.io.IOException;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;

class MyTestClass {

    private long id;
    private String name;
    private String notInterstingMember;
    private int anotherMember;
    private int forgetThisField;

    public long getId() {
        return this.id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public String getName() {
        return this.name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @JsonIgnore
    public String getNotInterstingMember() {
        return this.notInterstingMember;
    }

    public void setNotInterstingMember(String notInterstingMember) {
        this.notInterstingMember = notInterstingMember;
    }

    public int getAnotherMember() {
        return this.anotherMember;
    }

    public void setAnotherMember(int anotherMember) {
        this.anotherMember = anotherMember;
    }

    public int getForgetThisField() {
        return this.forgetThisField;
    }

    @JsonIgnore
    public void setForgetThisField(int forgetThisField) {
        this.forgetThisField = forgetThisField;
    }

    @Override
    public String toString() {
        return "MyTestClass [" + this.id + " , " +  this.name + ", " + this.notInterstingMember + ", " + this.anotherMember + ", " + this.forgetThisField + "]";
    }

}
{"id":1,"name":"Test program","anotherMember":100}
MyTestClass [1 , Test program, null, 100, 0]

See also:

The code of the 3 different examples described in the post can be downloaded here:

This entry was posted in Jackson, Java / JEE, JSON, Programming and tagged , , . Bookmark the permalink.

16 thoughts on “Jackson JSON: difference between @JsonIgnore and @JsonIgnoreProperties annotations

  1. Pingback: Jackson: using @JsonIgnore and @JsonProperty annotations to exclude a property only from JSON deserialization | Dede Blog

  2. Hi,
    if i have below json to read.
    {
    “app_id” : 1,
    “app_name” : “sam”,
    “age”: 23,
    “work_status”: “employed”
    }

    How can i just read “app_id” and “app_name”?
    i dont want to explicitly ignore other fields as in future some other fields might be added in the json which i dont want to read. And i dont want to change my code everytime it happen.

  3. How can I ignoreunknown and also ignore some known properties?
    @JsonIgnoreProperties(ignoreUnknown=true {“playStyleId”, “height”})

  4. @JsonIgnore is behaving differently when i tried it on local it works. However when deployed on server it is not working. I found that the java version is different on local and server. Locally it is 1.7 and on server it is 1.8. Does that impact?

Leave a Reply

Your email address will not be published. Required fields are marked *