Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Deserializing XML with list using Jackson

I have the following XML that I'd like to deserialize to Java POJO.

<testdata>
    <foo>
        <bar>
            <![CDATA[MESSAGE1]]>
        </bar>
        <bar>
            <![CDATA[MESSAGE2]]>
        </bar>
        <bar>
            <![CDATA[MESSAGE3]]>
        </bar>
    </foo>
</testdata>

I have the following Java classes

public class TestData {

    @JacksonXmlProperty(localName = "foo")
    private Foo foo;

    public Foo getFoo() {
        return foo;
    }

    public void setFoo(Foo foo) {
        this.foo = foo;
    }

}

I have another class like below

public class Foo {

    @JacksonXmlProperty(localName = "bar")
    @JacksonXmlCData
    private List<String> barList;

    public List<String> getBarList() {
        return barList;
    }

    public void setBarList(List<String> barList) {
        this.barList = barList;
    }
}

Now when I run the code using the class below I get an exception

private void readXml() throws FileNotFoundException, IOException {
    File file = new File("/Users/temp.xml");
    XmlMapper xmlMapper = new XmlMapper();
    String xml = GeneralUtils.inputStreamToString(new FileInputStream(file));
    TestData testData = xmlMapper.readValue(xml, TestData.class);
    System.out.println(testData.getFoo()
                               .getBarList());
}

Exception in thread "main" com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize instance of java.util.ArrayList out of VALUE_STRING token

How do I convert bar elements into a List? I tried multiple things but I keep getting some or the other errors

like image 527
Damien-Amen Avatar asked Mar 07 '18 15:03

Damien-Amen


2 Answers

You need to indicate that <bar> is a wrapping element for your collection of String messages:

This should work in your Foo class:

@JacksonXmlProperty(localName = "bar")
@JacksonXmlCData
@JacksonXmlElementWrapper(useWrapping = false)
private List<String> barList;
like image 188
hovanessyan Avatar answered Sep 22 '22 03:09

hovanessyan


In case you have in your input xml a list of bar elements with an attribute like

<testdata>
    <foo>
        <bar name="John">
            <![CDATA[MESSAGE1]]>
        </bar>
        <bar name="Mary">
            <![CDATA[MESSAGE2]]>
        </bar>
        <bar name="Bill">
            <![CDATA[MESSAGE3]]>
        </bar>
    </foo>
<testdata>

you could create a Bar class and include a list of it as a field of the Foo class:

    @JacksonXmlProperty(localName = "bar")
    @JacksonXmlElementWrapper(useWrapping = false)
    private List<Bar> barList;

The Bar class would be:

    class Bar {    
        @JacksonXmlProperty(isAttribute = true)
        private String name; 

        @JacksonXmlCData
        private String content;
   }

Remember to include getters and setters for the Bar class.

like image 28
gambarimas87 Avatar answered Sep 25 '22 03:09

gambarimas87