jackson-databind
jackson-databind copied to clipboard
JsonView doesn't work with JsonCreator
Consider the following example:
public static class View {
}
public static class View1 extends View {
}
public static class View2 extends View {
}
@Test
public void jacksonTest1() throws Exception {
ObjectMapper om = new ObjectMapper();
ObjectWriter w1 = om.writerWithView(View1.class);
ObjectWriter w2 = om.writerWithView(View2.class);
ObjectReader r1 = om.readerFor(Obj.class).withView(View1.class);
ObjectReader r2 = om.readerFor(Obj.class).withView(View2.class);
Obj o = new Obj("a", "b", "c");
String so0 = om.writeValueAsString(o);
System.out.println(so0); // {"a":"a","b":"b","c":"c"}
String so1 = w1.writeValueAsString(o);
System.out.println(so1); // {"a":"a","b":"b"}
String so2 = w2.writeValueAsString(o);
System.out.println(so2); // {"a":"a","c":"c"}
System.out.println(r1.readValue(so0).toString()); // See below
}
(1) Obj definition without @JsonCreator
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.PUBLIC_ONLY,
isGetterVisibility = JsonAutoDetect.Visibility.NONE,
getterVisibility = JsonAutoDetect.Visibility.NONE)
@JsonIgnoreProperties(ignoreUnknown = true)
public static class Obj {
public String a;
@JsonView(View1.class)
public String b;
@JsonView(View2.class)
public String c;
public Obj() {
}
public Obj() {
}
public Obj(String a,
String b,
String c) {
this.a = a;
this.b = b;
this.c = c;
}
@Override
public String toString() {
return "Obj{" +
"a='" + a + '\'' +
", b='" + b + '\'' +
", c='" + c + '\'' +
'}';
}
}
(2) Obj definition with @JsonCreator
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.PUBLIC_ONLY,
isGetterVisibility = JsonAutoDetect.Visibility.NONE,
getterVisibility = JsonAutoDetect.Visibility.NONE)
@JsonIgnoreProperties(ignoreUnknown = true)
public static class Obj {
public String a;
@JsonView(View1.class)
public String b;
@JsonView(View2.class)
public String c;
public Obj() {
}
@JsonCreator
public Obj(@JsonProperty("a") String a,
@JsonProperty("b") String b,
@JsonProperty("c") String c) {
this.a = a;
this.b = b;
this.c = c;
}
@Override
public String toString() {
return "Obj{" +
"a='" + a + '\'' +
", b='" + b + '\'' +
", c='" + c + '\'' +
'}';
}
}
The problem:
Example works with first (1) variant of Obj definition. And outputs:
Obj{a='a', b='b', c='null'}
but fails to ignore field c
with Obj defined with JsonCreator (2):
Obj{a='a', b='b', c='c'}
If someone also experiencing the same issue here's the temporary fix. You can put the @JsonView
annotation on every method's parameter.
@JsonCreator
public Obj(@JsonProperty("a") String a,
@JsonProperty("b") @JsonView(View1.class) String b,
@JsonProperty("c") @JsonView(View2.class) String c) {
this.a = a;
this.b = b;
this.c = c;
}
Note: suspecting this is due to issues with combining annotations between "regular" and @JsonCreator
(constructor parameter) properties. So it would (need to be) fixed if and when Property Introspection handling is rewritten to allow proper merging of all annotations.
#4173 proves this has been fixed, after idk, like 4 versions 🤔
@JooHyukKim better late verification than never :)