POJO object for this XML response in kotlin

Viewed 5076

I'm working with an API which returns XML something like this:

<xyz-objects version="1.0">
    <object pk="1" model="roll">
        <field type="BigIntegerField" name="roll_number">1000000714</field>
        <field type="CharField" name="status">DL</field>
        <field name="scans">
            <object pk="1" model="scan_stages">
                <field type="DateTimeField" name="updated_on">11 Jul, 2017, 17:40</field>
            </object>
        </field>        
    </object>
</xyz-objects>

I'm using Jackson's XML mapper.

I tried writing a POJO object for this but that doesn't work.

How do I handle attributes of elements like type and name? Can you exemplify?

2 Answers

As you didn't provide the schema, it's hard to guess some parts of your model. Especially, it's hard to guess field model. So I will deserialize it into a JsonNode, dynamic object that can handle literally everything. JsonIgnoreProperties just in case you have some extra fields, not mentioned here.

First, create some data classes:

@XmlRootElement(name = "xyz-objects")
@JsonIgnoreProperties(ignoreUnknown = true)
data class XyzObjects(
        @JacksonXmlProperty(isAttribute = true)
        val version: String,

        @JsonProperty(value = "object")
        @JacksonXmlElementWrapper(useWrapping = false)
        val objects: List<Object>
)

@XmlRootElement(name = "object")
@JsonIgnoreProperties(ignoreUnknown = true)
data class Object(
        @JacksonXmlProperty(isAttribute = true)
        val pk: String,

        @JacksonXmlProperty(isAttribute = true)
        val model: String,

        @JsonProperty(value = "field")
        @JacksonXmlElementWrapper(useWrapping = false)
        val fields: List<JsonNode>
)

Answering your question: you can handle attrributes with by using isAttribute attribute of JacksonXmlProperty. Lists can be handled with JacksonXmlElementWrapper + JsonProperty (don't be fooled by name, it is used to handle plurals in names, thus making them more human readable in XML too).

In order to be able to work with data classes, you'll need to register Kotlin module with registerKotlinModule:

val text = """<xyz-objects version="1.0">
<object pk="1" model="roll">
    <field type="BigIntegerField" name="roll_number">1000000714</field>
    <field type="CharField" name="status">DL</field>
    <field name="scans">
        <object pk="1" model="scan_stages">
            <field type="DateTimeField" name="updated_on">11 Jul, 2017, 17:40</field>
        </object>
    </field>
</object>
</xyz-objects>"""
val mapper = XmlMapper().registerKotlinModule()
val node = mapper.readValue<XyzObjects>(text)

println(node)

It will print:

XyzObjects(version=1.0, objects=[Object(pk=1, model=roll, fields=[{"type":"BigIntegerField","name":"roll_number","":"1000000714"}, {"type":"CharField","name":"status","":"DL"}, {"name":"scans","object":{"pk":"1","model":"scan_stages","field":{"type":"DateTimeField","name":"updated_on","":"11 Jul, 2017, 17:40"}}}])])
Related