Search code examples
javaxmljacksonjackson-dataformat-xml

Can not parse xml root element use jackson


Test Bean

@JacksonXmlRootElement(localName = "DATA_RECORD")
public class TestBean{
    @JacksonXmlProperty(localName="ERROR_MESSAGE_CODE")
    private String error_message_code;
    @JacksonXmlProperty(localName="ERROR_MESSAGE")
    private String error_message;
    //...getter/setter
}

XMl Sample

String xml = "<?xml version=\"1.0\" encoding=\"Windows-31J\" standalone=\"no\"?>"
            + "<Message xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" "
            //+">"
            + "xsi:noNamespaceSchemaLocation=\"TEST.xsd\">" // if comment out this,it will work.
            + "<DATA_RECORD>"
            + "<ERROR_MESSAGE>some message</ERROR_MESSAGE>"
            + "<ERROR_MESSAGE_CODE>CODE111</ERROR_MESSAGE_CODE>"
            + "</DATA_RECORD>"
            + "</Message>";

Deserialize

XmlMapper xmlMapper = new XmlMapper();
//xmlMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
xmlMapper.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, true);
TestBean test = xmlMapper.readValue(xml, TestBean.class);
log.debug(test.toString());

I run it from Junit and I get exception like:

Root name 'noNamespaceSchemaLocation' does not match expected ('DATA_RECORD') ....

If I remove xsi:noNamespaceSchemaLocation="TEST.xsd" from String xml, it will work fine.

Have idea about this? Thanks for help.


Solution

  • According to the docs, when you specify UNWRAP_ROOT_VALUE, Jackson (XML here instead of JSON)

    Will verify that the root JSON value is a JSON Object, and that it has a single property with expected root name. If not, a JsonMappingException is thrown;

    In this case the root Message has another property apart from DATA_RECORD, the XML attribute with name noNamespaceSchemaLocation and as specified a JsonMappingException is thrown.

    I am afraid you will have to parse Message and get TestBean from there. E.g.:

    @JacksonXmlRootElement
    class Message {
        @JacksonXmlProperty(localName = "DATA_RECORD")
        private TestBean dataRecord;
    }
    
    class TestBean {
        @JacksonXmlProperty(localName = "ERROR_MESSAGE_CODE")
        private String error_message_code;
        @JacksonXmlProperty(localName = "ERROR_MESSAGE")
        private String error_message;
    }
    

    and

    xmlMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
    Message test = xmlMapper.readValue(xml, Message.class);
    log.debug(test.getDataRecord().toString());