简体   繁体   中英

How do you deserialize XML without multiple wrapper classes?

I have some XML that I want to turn into an object using Jackson FasterXML. The XML looks like this:

<services>
    <service id="1" name="test">
        <addresses>
            <postalAddress id="2" line1="123 Fake Street" city="Springfield" />
        </addresses>
    </service>
</services>

I am deserializing this as an object successfully with these classes:

JsonIgnoreProperties(ignoreUnknown = true)
@JacksonXmlRootElement(localName = "services")
public class ServiceWrapper {
    @JacksonXmlProperty(localName = "service")
    private Service service;
    //Getters and setters [...]
}

@JsonIgnoreProperties(ignoreUnknown = true)
public class Service {
    @JacksonXmlProperty(isAttribute = true)
    private int id;
    @JacksonXmlProperty(isAttribute = true)
    private String name;
    @JacksonXmlProperty(localName = "addresses")
    private AddressWrapper addresses;
    //Getters and setters [...]
}

public class AddressWrapper {
    @JacksonXmlProperty(localName = "postalAddress")
    private List<Address> addresses;
    //Getters and setters [...]
}

@JsonIgnoreProperties(ignoreUnknown = true)
public class Address {
    @JacksonXmlProperty(isAttribute = true, localName = "id")
    private int id;
    @JacksonXmlProperty(isAttribute = true, localName = "line1")
    private int address1;
    @JacksonXmlProperty(isAttribute = true, localName = "city")
    private int city;
    //Getters and setters [...]
}

And the code to do the mapping:

JacksonXmlModule module = new JacksonXmlModule();
module.setDefaultUseWrapper(false);

ObjectMapper mapper = new XmlMapper(module);
mapper.registerModule(new JSR310Module());
mapper.configure(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS, true);

ServiceWrapper serviceWrapper = mapper.readValue(xmlString, ServiceWrapper.class);
return serviceWrapper.getService();

This all works fine, but it's a lot of overhead and ugly code to have the ServiceWrapper and AddressWrapper classes; when really all I want is the data in the <service> node and <postalAddress> node. Is it possible to tell the Jackson object to directly populate a list of Addresses in my Service class without having the AddressWrapper class to represent the <addresses> node? Similarly to take the entire xml and populate a Service class directly without needing a ServiceWrapper class?

The normal way to avoid writing/maintaining such code is to use JAXB to generate the Java code (with appropriate annotations). This process uses an XML schema (.xsd) as the input, with an optional bindings file (.xjb) to customize the generated code.

It looks like many of the JAXB annotations are supported by Jackson .

I will also note that JAXB code generator (xjc) supports plugins that allow you to do pretty much anything you want to augment the generated code (eg, with additional methods or annotations).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM