Jackson XML deserialize Sub-Nodes as Plain String

Viewed 536

I have an XML Sttructure and want to Deserialize this to an Object with a Property Description as a Plain HTML-String

<ItemList>
  <Item ID="1">
    <Description>
      <p>
        <span>This is a HTML Description</span>
      </p>
      <p>
        With undefined number of subnodes
      </p>
    </Description>
  </Item>
  <Item ID="2">
    <Description>
      <p>
        <span>This is a HTML Description</span>
      </p>
      <ul>
        <li>Some Other Nodes</li>
      </ul>
    </Description>
  </Item>
</ItemList>

The description tag contains only HTML text and i don't want to define classes for all possible HTML-Tags. Is there a solution, for example with a custom Deserializer, to parse the Tags inside Description as Plain Html-Text?

My classes look like this

data class ItemList(
  @JacksonXmlProperty(localName = "Item")
  @JacksonXmlElementWrapper(useWrapping = false)
  val items: List<Item> = listOf()
)

data class Item(
  @JacksonXmlProperty(localName = "ID", isAttribute = true)
  val id: String? = null,


  @JacksonXmlProperty(localName = "Description")
  val description: HtmlText? = null
)

data class HtmlText(
  val text: String? // This should be the Plain HTML-String
)
private val xmlMapper = XmlMapper()
    .registerKotlinModule()
    .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)

val itemlist = xmlMapper.readValue<ItemList>(stream) // stream is the XML file described above
1 Answers

I'm not as well versed in Kotlin, so I wrote up the Java that should be cover this. Basically, you need to accept the ObjectNode in the mutator so that you can serialize it back to XML using a XML Mapper.

public class TestMe3 {
    public static void main(String[] args) throws IOException, XMLStreamException {
        var inputString =
                "<ItemList>\n" +
                        "   <Item ID=\"1\">\n" +
                        "       <Description>\n" +
                        "           <p>\n" +
                        "               <span>This is a HTML Description</span>\n" +
                        "           </p>\n" +
                        "           <p>\n" +
                        "               With undefined number of subnodes\n" +
                        "           </p>\n" +
                        "       </Description>\n" +
                        "   </Item>\n" +
                        "   <Item ID =\"2\">\n" +
                        "       <Description>\n" +
                        "           <p>\n" +
                        "               <span> This is a HTML Description</span>\n" +
                        "           </p>\n" +
                        "           <ul>\n" +
                        "               <li>Some Other Nodes</li>\n" +
                        "           </ul>\n" +
                        "       </Description>\n" +
                        "   </Item>\n" +
                        "</ItemList>";
        Reader reader = new StringReader(inputString);
        XMLInputFactory factory = XMLInputFactory.newInstance(); // Or newFactory()
        XMLStreamReader xmlReader = factory.createXMLStreamReader(reader);

        XmlMapper xmlMapper = new XmlMapper();
        xmlMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        ItemList returnObj = xmlMapper.readValue(xmlReader, ItemList.class);
        System.out.println(returnObj.items.get(0).description);
        System.out.println(returnObj.items.get(1).description);
    }


    @JacksonXmlRootElement(localName = "ItemList")
    static class ItemList {
        @JacksonXmlProperty(localName = "Item")
        @JacksonXmlElementWrapper(useWrapping = false)
        List<Item> items;
    }

    @JacksonXmlRootElement(localName = "Item")
    static class Item {
        @JacksonXmlProperty(localName = "ID", isAttribute = true)
        String id;

        @JacksonXmlElementWrapper(localName = "Description")
        String description;

        public void setDescription(ObjectNode xml) throws JsonProcessingException {
            XmlMapper xmlMapper = new XmlMapper();
            description = xmlMapper.writer().withRootName("Description").writeValueAsString(xml);
        }
    }

}
Related