Moiz Noorani
Moiz Noorani

Reputation: 43

Deserializing xml with duplicate nested tags with Jackson

I'm trying to deserialize some xml with nested properties with the same name, but the wrapper name is unique for each property. Example XML below.

I've tried playing with switching wrapper and property names but doesn't seem to work.

<response>
    <string>
        <item>Sample string.</item>
        <item>Another sample string.</item>
    </string>
    <number>
        <item>123123123</item>
        <item>900912</item>
    </number>
</response>

I'm trying to deserialize the above XML into a List<String> and List<Integer> variable.

Upvotes: 3

Views: 2029

Answers (2)

Michał Ziober
Michał Ziober

Reputation: 38720

For version 2.9.9 simple POJO with JacksonXmlElementWrapper annotation works as expected:

class Response {

    @JacksonXmlElementWrapper(localName = "string")
    private List<String> strings;

    @JacksonXmlElementWrapper(localName = "number")
    private List<Integer> numbers;

    // getters, setters
}

Upvotes: 1

jlumietu
jlumietu

Reputation: 6444

I managed to make it creating a pair or wrappers of ArrayLists as inner classes:

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;

@JacksonXmlRootElement(localName="response")
public class ResponseObjectList implements Serializable {

    @JacksonXmlProperty(localName = "string")
    private StringArrayListContainer string;

    @JacksonXmlProperty(localName = "number")
    private IntegerArrayListContainer number;

    public ResponseObjectList() {
        super();
    }

    public ResponseObjectList(List<String> stringItems, List<Integer> intItems) {
        super();
        this.string = new StringArrayListContainer(stringItems);
        this.number = new IntegerArrayListContainer(intItems);
    }

    public StringArrayListContainer getString() {
        return string;
    }

    public void setString(StringArrayListContainer string) {
        this.string = string;
    }

    public IntegerArrayListContainer getNumber() {
        return number;
    }

    public void setNumber(IntegerArrayListContainer number) {
        this.number = number;
    }

    public static class StringArrayListContainer extends ArrayListContainer<String>{

        public StringArrayListContainer() {
            super();
        }

        public StringArrayListContainer(List<String> item) {
            super(item);
        }

    }

    public static class IntegerArrayListContainer extends ArrayListContainer<Integer>{

        public IntegerArrayListContainer() {
            super();
        }

        public IntegerArrayListContainer(List<Integer> item) {
            super(item);
        }

    }

    public static class ArrayListContainer<T extends Serializable>{ 

        @JacksonXmlElementWrapper(useWrapping=false)
        @JacksonXmlProperty(localName="item")
        private List<T> item;

        public ArrayListContainer(List<T> item) {
            super();
            this.item = item;
        }

        public ArrayListContainer() {
            super();
        }

        public List<T> getItem() {
            return item;
        }

        public void setItem(List<T> item) {
            this.item = item;
        }

    }

}

Tests looked good:

@Test
    public void test3() throws JsonProcessingException {
        ResponseObjectList response = new ResponseObjectList(
                    Arrays.asList(new String[] {"Sample string.","Another sample string"}),
                    Arrays.asList(new Integer[] {123123123,900912})
                );
        XmlMapper xmlMapper = new XmlMapper();
        String content = xmlMapper.writeValueAsString(response);
        this.logger.debug("content: " + content);
        // content: <response xmlns=""><string><item>Sample string.</item><item>Another sample string</item></string><number><item>123123123</item><item>900912</item></number></response>
    }

    @Test
    public void test4() throws JsonParseException, JsonMappingException, IOException {
        String xml = 
                "<response>"
                + "<string>"
                + "<item>Sample string.</item>"
                + "<item>Another sample string</item>"
                + "</string>"
                + "<number>"
                + "<item>123123123</item>"
                + "<item>900912</item>"
                + "</number>"
                + "</response>";

        XmlMapper xmlMapper = new XmlMapper();
        ResponseObjectList object = xmlMapper.readValue(xml, ResponseObjectList.class);
        Assert.assertFalse(object.getString().getItem().isEmpty());
        Assert.assertFalse(object.getNumber().getItem().isEmpty());
    }

I used Lists instead of ArrayLists both for the wrappers and the tests

Upvotes: 2

Related Questions