kotlin - Jackson Xml parsing chooses attribute instead of tag - Stack Overflow

admin2025-04-18  3

I have this xml file:

<?xml version="1.0" encoding="iso-8859-1" standalone="yes"?>
<nms:nmsDocument xmlns:nms="; xmlns:xsi=";>
    <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

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

Share Improve this question edited Jan 30 at 19:07 Georgii Lvov 3,1351 gold badge8 silver badges29 bronze badges asked Jan 30 at 16:21 Semyon VolokhSemyon Volokh 133 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 0

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.

转载请注明原文地址:http://anycun.com/QandA/1744906175a89293.html