using jackson 2.x
the json response looks like this:
{
"flag": true,
"important": {
"id": 123,
"email": "[email protected]"
}
}
The "flag" key does not provide any useful information. I would like to ignore the "flag" key and unwrap the "important" value to an instance of Important.
public class Important {
private Integer id;
private String email;
public Important(@JsonProperty("id") Integer id,
@JsonProperty("email") String email) {
this.id = id;
this.email = email;
}
public String getEmail() { this.email }
public Integer getId() { this.id }
}
When I try to add a @JsonRootName("important") to Important and configure the ObjectMapper with DeserializationFeature.UNWRAP_ROOT_VALUE I receive a JsonMappingException:
Root name 'flag' does not match expected ('important') for type ...
When i remove the "flag" key/value from the JSON the data binding works just fine. I get the same result if i add @JsonIgnoreProperties("flag") to Important as well.
UPDATES
@JsonRootName("important")
public static class Important {
private Integer id;
private String email;
@JsonCreator
public Important(@JsonProperty("id") Integer id,
@JsonProperty("email") String email) {
this.id = id;
this.email = email;
}
public String getEmail() { return this.email; }
public Integer getId() { return this.id; }
}
actual test:
@Test
public void deserializeImportant() throws IOException {
ObjectMapper om = new ObjectMapper();
om.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
om.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, true);
Important important = om.readValue(getClass().getResourceAsStream("/important.json"), Important.class);
assertEquals((Integer)123, important.getId());
assertEquals("[email protected]", important.getEmail());
}
results:
com.fasterxml.jackson.databind.JsonMappingException: Root name 'flag' does not match expected ('important') for type [simple type, class TestImportant$Important]
Just because of streaming nature of JSON parsing in Jackson, I'm afraid there is no easy way of handling such cases.
From my point of view, it's easier to do with some sort of wrapper.
Consider this code:
public static class ImportantWrapper {
@JsonProperty("important")
private Important important;
public Important getImportant() {
return important;
}
}
And actual test:
@Test
public void deserializeImportant() throws IOException {
ObjectMapper om = new ObjectMapper();
//note: this has to be present
om.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
Important important = om.readValue(getClass().getResourceAsStream("/important.json"), ImportantWrapper.class)
.getImportant();
assertEquals((Integer)123, important.getId());
assertEquals("[email protected]", important.getEmail());
}
Note, that @JsonRootName("important")
is redundant and can be removed in this case.
This looks some sort of ugly, but works perfectly with relatively small effort. Also such "wrappers" can be generified, but this is more like architecture's stuff.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With