Jackson-databind: Duplicate properties with upper-case field name and JsonProperty annotation

Created on 19 Apr 2017  路  6Comments  路  Source: FasterXML/jackson-databind

Duplicate properties with upper-case field name and JsonProperty annotation

  • Jackson version: 2.8.8
  • TestCase
public class JacksonTest {
    public static void main(String[] args) {

        ObjectMapper  objectMapper = new ObjectMapper();
        Person person = new Person("neal", 30);

        try {
            objectMapper.writerWithDefaultPrettyPrinter().writeValue(System.out, person);
            //new ByteArrayInputStream(objectMapper.writeValueAsBytes(person));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static class Person {

        Person(String name, int age) {
            this.Name = name;
            this.Age = age;
        }

        public String getName() {
            return Name;
        }

        public void setName(String name) {
            Name = name;
        }

        public int getAge() {
            return Age;
        }

        public void setAge(int age) {
            Age = age;
        }

        @JsonProperty("Name")
        private String Name;

        @JsonProperty("Age")
        private int Age;

    }
}
  • Output:
{
  "name" : "neal",
  "age" : 30,
  "Name" : "neal",
  "Age" : 30
}

Expected:

{
  "Name" : "neal",
  "Age" : 30
}
  • Suspect cause:
    com.fasterxml.jackson.databind.ser.BeanSerializerFactory:138

Neal

Most helpful comment

It works because all accessors initially match: "getAge()", "setAge()" and "age" infer age; and renaming of one renames them all as Age. Same for "name". Introspection always starts by checking inferred name: getters and setters use bean naming convention, field names used as is.
Accessors with same inferred name are grouped into one logical property candidate. After this, annotations are checked and apply to candidates, as a group.

All 6 comments

Not a bug but results from incompatible field/getter/setter naming -- fields would imply properties Name and Age (no annotation needed), but setters would imply properties name and age. Those will not automatically match (there is no assumption of case unification), so you end up with twice the properties you expect.

Fortunately there is a simple fix: just move annotations to either setters or getters (either one is fine): this will allow otherwise separate fields and getter/setter pairs to match

Why this works well? Fields introduce Name and Age, setters introduce name and age?

private static class Person {

        Person(String name, int age) {
            this.name = name;
            this.age = age;
        }

        public String getName() {
            return name;
        }

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

        public int getAge() {
            return age;
        }

        public void setAge(int age) {
            this.age = age;
        }

        @JsonProperty("Name")
        private String name;

        @JsonProperty("Age")
        private int age;

    }

It works because all accessors initially match: "getAge()", "setAge()" and "age" infer age; and renaming of one renames them all as Age. Same for "name". Introspection always starts by checking inferred name: getters and setters use bean naming convention, field names used as is.
Accessors with same inferred name are grouped into one logical property candidate. After this, annotations are checked and apply to candidates, as a group.

I have an instance where for below fields in my pojo:

private String oCurrNod;
public String getOCurrNod() {
    return this.oCurrNod;
}
public void setOCurrNod(String oCurrNod) {
    this.oCurrNod = oCurrNod;
}

During conversion from POJO to json it introduces new field: ocurrNod apart from the original field oCurrNod. Can you please comment on why would this be even though this naming convention seems to be right?

I also tried adding @JsonProperty annotation to getter to see if that fixes as suggested above in the comments. But this change doesn't fix the issue. I am using jackson 2.4.4

@ronikraja Please use mailing list:

https://groups.google.com/forum/#!forum/jackson-user

for usage questions. Adding questions on closed issues is not a good medium for those.
If posting, include code to reproduce behavior (class definition is often not enough in itself).
It is also good to use a newer version of Jackson; 2.4.4 is rather old at this point.

But I can speculate on the problem: names are not compatible, due to inconsistent capitalization of the first 2 letters (field has 1; accessors 2).

mark

Was this page helpful?
0 / 5 - 0 ratings