I have this xml file:
<?xml version="1.0" encoding="iso-8859-1" standalone="yes"?>
<nms:nmsDocument xmlns:nms="http://www.nms.com/xml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<nms:nmsObject xsi:type="nms:Test">
<nms:type>
<nms:domainValue>
<nms:name>"Hello"</nms:name>
</nms:domainValue>
</nms:type>
</nms:nmsObject>
</nms:nmsDocument>
I need to parse it and get the value of <nms:name> which is "Hello".
I've written these classes:
@JacksonXmlRootElement(localName = "nmsDocument", namespace = "nms")
@JsonIgnoreProperties(ignoreUnknown = true)
data class NmsDocument(
@JacksonXmlProperty(localName = "nmsObject", namespace = "nms")
val nmsObject: NmsObject
)
@JsonIgnoreProperties(ignoreUnknown = true)
data class NmsObject(
@JacksonXmlProperty(localName = "type", namespace = "nms", isAttribute = false)
val type: Type
)
@JsonIgnoreProperties(ignoreUnknown = true)
data class Type(
@JacksonXmlProperty(localName = "domainValue", namespace = "nms")
val domainValue: DomainValue
)
@JsonIgnoreProperties(ignoreUnknown = true)
data class DomainValue(
@JacksonXmlProperty(localName = "name", namespace = "nms")
val name: String
)
The error is:
Exception in thread "main" com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of com.example.demo.Type
(although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('nms:Test')
at [Source: (StringReader); line: 3, column: 5] (through reference chain: com.example.demo.NmsDocument["nmsObject"]->com.example.demo.NmsObject["type"])
It tries to parse attribute xsi:type from <nms:nmsObject> tag instead of <nms:type> tag which is in <nms:nmsObject>. Is there any solution to that? Nothing helps to fix it.
It is advisable to implement this using the Jackson lib
You can write a custom deserializer for NmsObject
class. Like this:
class NmsObjectDeserializer : StdDeserializer<NmsObject>(NmsObject::class.java) {
override fun deserialize(parser: JsonParser, ctxt: DeserializationContext): NmsObject {
val node: JsonNode = parser.codec.readTree(parser)
val type = parser.codec.treeToValue(node.get("type").get(1), Type::class.java)
return NmsObject(type)
}
}
and
@JsonDeserialize(using = NmsObjectDeserializer::class)
@JsonIgnoreProperties(ignoreUnknown = true)
data class NmsObject(
@JacksonXmlProperty(localName = "type", namespace = "nms", isAttribute = false)
val type: Type
)
You should use 1
in this line node.get("type").get(1)
, the 1st item is the attribute.