I'm referencing a web service that returns an array in the format:
{
"ZooAnimals": {
"@size": "2",
"Animal": {
"0": {
"@name": "elephant",
"@size": "huge"
},
"1": {
"@name": "termite",
"@size": "verysmall"
}
}
}
}
If requested in XML format it returns:
<ZooAnimals size="2">
<Animal name="elephant" size="huge"></Animal>
<Animal name="termite" size="very small"></Animal>
</ZooAnimals>
I am writing a test to verify that it gets deserialized properly into a Java class. The XML works properly, but the JSON (using jackson) gives an error: Unrecognized field "0" not marked as ignorable.
I do not control the JSON response and would prefer to use a single class to receive the deserialized contents. The class I inherited was annotated like this:
@XmlAccessorType(XmlAccessType.FIELD)
@JsonInclude(JsonInclude.Include.NON_DEFAULT)
@JsonTypeName("ZooAnimals")
public class ZooAnimals {
@XmlAttribute
@JsonProperty("@size")
private String size;
@XmlElement(name = "Animal", required = false)
@JsonProperty("Animal")
private List<Animal> animalList;
...
}
@XmlAccessorType(XmlAccessType.FIELD)
@JsonInclude(JsonInclude.Include.NON_DEFAULT)
@JsonTypeName("Animal")
public class Animal {
@XmlAttribute
@JsonProperty("@name")
private String name;
@XmlAttribute
@JsonProperty("@size")
private String size;
...
}
Is there a way to annotate this class so that jackson can deserialize the text above without my having to write custom code? As an aside, maintaining ordering is not a requirement.
You have to use JsonAnySetter annotation and your ZooAnimals class should look like this:
@XmlAccessorType(XmlAccessType.FIELD)
@JsonInclude(JsonInclude.Include.NON_DEFAULT)
@JsonTypeName("ZooAnimals")
class ZooAnimals {
@XmlAttribute
@JsonProperty("@size")
private String size;
@XmlElement(name = "Animal", required = false)
private List<Animal> animalList;
@JsonAnySetter
public void setAny(String propertyName, Map<String, Animal> map) {
animalList = new ArrayList<Animal>(map.values());
}
// getters, setters, toString
}
You do not have to change Animal class at all. Below program:
ObjectMapper mapper = new ObjectMapper();
mapper.enable(DeserializationFeature.UNWRAP_ROOT_VALUE);
ZooAnimals zooAnimals = mapper.readValue(XML, ZooAnimals.class);
System.out.println(zooAnimals);
prints:
ZooAnimals{size='2', animalList=[Animal{name='elephant', size='huge'}, Animal{name='termite', size='verysmall'}]}
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