Jackson: using @JsonIgnore and @JsonProperty annotations to exclude a property only from JSON deserialization

In the previous article we saw how and where to use the Jackson @JsonIgnore annotation to exclude a property of an Java object from the JSON serialization. Not being available, the value of that property, during deserialization will be set to the default value in accordance with its type. In this case, therefore, the process is symmetrical, in the sense that the property value is ignored by both serialization and deserialization operations.
If we want to make it asymmetrical, that is, to exclude a Java object property only during deserialization, but instead to include its value during JSON serialization we must use an appropriate combination of @JsonIgnore and @JsonProperty annotations. To be precise, we must:

  • annotate with @JsonIgnore the property itself
  • annotate with @JsonIgnore its set method
  • annotate with @JsonProperty its get method

We take the example already used in the previous post and see how to configure MyTestClass class so that the field “forgetThisField” is serialized in JSON but its value is then ignored during deserialization.

import java.io.IOException;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
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;

    @JsonIgnore
    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;
    }

    @JsonProperty
    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 + "]";
    }
}


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(999);

        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());

    }
}

As we saw earlier, it’s necessary to:

  • annotate with @JsonIgnore the “forgetThisField” property
  •  
    @JsonIgnore 
    private int forgetThisField; 
    
  • annotate with @JsonIgnore its set method “setForgetThisField”
  •  
    @JsonIgnore 
    public void setForgetThisField (int forgetThisField) { 
    this.forgetThisField = forgetThisField; 
    } 
    
  • annotate with @JsonProperty its get method, “getForgetThisField”
  •  
    @JsonProperty 
    public int getForgetThisField () { 
    this.forgetThisField return; 
    } 
    

Running the test program we get the following result:

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

As we can see, in the serialization the “forgetThisField” property is included with its value 999, while in the new object instantiated deserializing the string, this property is ignored and its value gets the default value of its type, that is, 0 being an int.

The important thing to consider is that the annotations must be all exactly as explained. If we omits some of those listed, we do not obtain the desired result. If, for example, we only put the @JsonIgnore annotation on the set method and the @JsonProperty annotation on the get method, but we do not put @JsonIgnore on the property, this is not ignored during deserialization:

 
class MyTestClass {

    private long id;
    private String name;
    private String notInterstingMember;
    private int anotherMember;
	
    //@JsonIgnore    			// COMMENTED
    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;
    }

    @JsonProperty
    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 + "]";
    }

}

By running the program again we get:

 
{"Id": 1, "name": "Test program", "anotherMember": 100, "forgetThisField": 999} 
MyTestClass [1, Test program, null, 100, 999] 

As we can see this time the property has not been ignored in the process of de-serialization and the serialized value is then set to the new object.

Similarly, if we put the @JsonIgnore annotation on the property and the @JsonProperty annotation on the get method, but we do not put @JsonIgnore on the set method, once again the indication to ignore the property is not applied to the deserialization:

class MyTestClass {

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

    @JsonIgnore
    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;
    }

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

    // @JsonIgnore				// COMMENTED
    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, "forgetThisField": 999} 
MyTestClass [1, Test program, null, 100, 999] 

8 thoughts on “Jackson: using @JsonIgnore and @JsonProperty annotations to exclude a property only from JSON deserialization

  1. Pingback: Jackson JSON: difference between @JsonIgnore and @JsonIgnoreProperties annotations | Dede Blog

  2. Is there a way to ignore null fields for all POJOs in the default Jakson serializer instead of annotating all of them ?

  3. Pingback: Jackson: escludere le proprietà con valore null dalla serializzazione JSON | Dede Blog

  4. Thanks for the post. Very useful. I am not sure I’d have thought to try adding the @JsonIgnore to the property declaration as well. Anyway, your notes about how to annotation the property declaration and the getter and setter worked perfectly. Thanks again.

Leave a Reply

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