Search code examples
javajacksonjackson-databind

How to deserialize JSON with @JsonCreator and @JsonGetter


I have the JSON looks like the following:

{
  "name":"John",
  "n_age":500
}

and I have a class Person:

public class Person {
    private final String name;
    private final int age;

    @JsonCreator
    public Person(@JsonProperty("name") String name) {
        this.name = name;
        this.age = 100;
    }

    public String getName() {
        return name;
    }

    @JsonGetter("n_age")
    public int getAge() {
        return age;
    }
}

I need to deserialize and serialize it, but when I'm trying to deserialize this JSON I get unexpected result.

public static void main(String... args) {
    ObjectMapper mapper = new ObjectMapper();
    Person person = mapper.readValue(args[0], Person.class);
    System.out.println(person.getAge()); // I got 500, but I expect 100.
}

Why when I'm trying to deserialize it the @JsonGetter annotation is used for it?
How can I disable @JsonGetter annotation when I try to deserialize the JSON?


Solution

  • If @JsonGetter is used as is currently, it will map property n_age to field age. To citate the docs - It can be used as an alternative to more general JsonProperty annotation (which is the recommended choice in general case).

    To fix this behaviour, you need to:

    1. Tell jackson to ignore property n_age, otherwise you will get exception for unrecognized property not marked as ignorable - @JsonIgnoreProperties("n_age").
    2. Tell jackson to allow getters for ignored properties(basically make it readonly) - @JsonIgnoreProperties(value = {"n_age"}, allowGetters = true)

    In the end, Person should look like this:

    @JsonIgnoreProperties(value = {"n_age"}, allowGetters = true)
    public class Person {
    
        private final String name;
        private final int age;
    
        @JsonCreator
        public Person(@JsonProperty("name") String name) {
            this.name = name;
            this.age = 100;
        }
    
        public String getName() {
            return name;
        }
    
        @JsonGetter("n_age")
        public int getAge() {
            return age;
        }
    
        @Override
        public String toString() {
            return "Person{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    '}';
        }
    }