Search code examples
javaxmlspring-bootjacksonxml-deserialization

Convert an empty tag in XML to java attribute using jackson-dataformat-xml library


I have below XML which need to be converted to POJO in Spring Boot app. I am using jackson-dataformat-xml module for this.

<Root>
    <Element1 ns="xxx">
        <Element2/>
    </Element1>
</Root>

Root Pojo:

@JacksonXmlRootElement(localName = "Root")
public class Root {
    @JacksonXmlProperty(localName = "Element1")
    private Element1 element1;

    public String getElement1() {
        return element1;
    }

    public void setElement1(String element1) {
        this.element1 = element1;
    }
}

Element1 Pojo:

public class Element1 {
    @JacksonXmlProperty(isAttribute = true)
    private String ns;
    
    @JacksonXmlProperty(localName = "Element2")
    private boolean element2;

    public boolean getElement2() {
        return element2;
    }

    public void setElement2(boolean element2) {
        this.element2 = element2;
    }
}

Property element2 in Element1 is always set to false. Is there any way to set it to true if Element2 tag is present; otherwise false?


Solution

  • By default Jackson uses com.fasterxml.jackson.databind.deser.BeanDeserializer class do deserialise given XML element to POJO. This deserialiser invokes setter method only if corresponding node exists in XML payload. In case, node doesn't exist in payload - setter method is not invoked. We can utilize this behaviour.

    Because we want to set always true we should create new private setter method and force Jackson to use it with @JacksonXmlProperty annotation. Below you can see example:

    class Element1 {
        @JacksonXmlProperty(isAttribute = true)
        private String ns;
    
        private boolean element2;
    
        public boolean getElement2() {
            return element2;
        }
    
        public void setElement2(boolean element2) {
            this.element2 = element2;
        }
    
        @JacksonXmlProperty(localName = "Element2")
        private void setElement2ByJackson(boolean ignored) {
            this.element2 = true;
        }
    }