Foo
Foo

Reputation: 4606

A way to serialize an into an XML with attributes in java

When I call an api, I get an xml response like this. I need to deserialize this into an object and then serialize it back to an xml of this same format.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Person version= "xyz">
    <properties>
        <name> John</name>
        <city>nyc</city>
    </properties>
</Person>

I am facing two challenges

1>The properties has a variable list. I need to serialize this into a Map<String,String>. (key:name->value:John, key:city->value:nyc, etc)

2>When I serialize the Person object back to XML how do I add version= "xyz" attribute?

Can someone help me?

Upvotes: 0

Views: 1178

Answers (1)

Andreas
Andreas

Reputation: 159114

You can use JAXB, with @XmlAnyElement for support of elements with arbitrary names.

The following works natively with Java 8. For Java 7, the stream logic in toString() needs to be changed to regular for loop. For Java 9+, where JAXB was removed, a JAXB library is needed.

@XmlRootElement(name = "Person")
@XmlAccessorType(XmlAccessType.NONE)
class Person {

    private String version;
    private List<Element> properties;

    @XmlAttribute
    public String getVersion() {
        return this.version;
    }

    public void setVersion(String version) {
        this.version = version;
    }

    @XmlElementWrapper(name = "properties")
    @XmlAnyElement
    public List<Element> getProperties() {
        return this.properties;
    }

    public void setProperties(List<Element> properties) {
        this.properties = properties;
    }

    public void addProperty(String name, String value) {
        try {
            Element elem = DocumentBuilderFactory.newInstance()
                    .newDocumentBuilder().newDocument().createElement(name);
            elem.setTextContent(value);
            if (this.properties == null)
                this.properties = new ArrayList<>();
            this.properties.add(elem);
        } catch (ParserConfigurationException e) {
            throw new IllegalStateException(e);
        }
    }

    @Override
    public String toString() {
        String propertiesAsString = this.properties.stream()
                .map(e -> e.getLocalName() + ": \"" + e.getTextContent() + "\"")
                .collect(Collectors.joining(", ", "[", "]"));
        return "Person[version=" + this.version + ", properties=" + propertiesAsString + "]";
    }

}

Test

Person person = new Person();
person.setVersion("xyz");
person.addProperty("name", " John");
person.addProperty("city", "nyc");

JAXBContext jaxbContext = JAXBContext.newInstance(Person.class);
Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
StringWriter xml = new StringWriter();
marshaller.marshal(person, xml);
System.out.println(xml);

Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
Person person2 = (Person) unmarshaller.unmarshal(new StringReader(xml.toString()));
System.out.println(person2);

Output

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Person version="xyz">
    <properties>
        <name> John</name>
        <city>nyc</city>
    </properties>
</Person>

Person[version=xyz, properties=[name: " John", city: "nyc"]]

Upvotes: 2

Related Questions