Duplicate properties with upper-case field name and JsonProperty annotation
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;
}
}
{
"name" : "neal",
"age" : 30,
"Name" : "neal",
"Age" : 30
}
Expected:
{
"Name" : "neal",
"Age" : 30
}
Neal
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
Most helpful comment
It works because all accessors initially match: "getAge()", "setAge()" and "age" infer
age; and renaming of one renames them all asAge. 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.