xmlutil icon indicating copy to clipboard operation
xmlutil copied to clipboard

Deserialization issues with 0.90.2+

Open hrkfdn opened this issue 1 year ago • 4 comments
trafficstars

This problem occurs with 0.90.2 and 0.90.3. See the following example:

class Test {
    @Serializable
    @SerialName("element")
    data class Element(
        @XmlElement(true)
        val a: String
    )

    @Serializable
    @SerialName("element")
    data class OtherElement(
        @XmlElement(true)
        val b: String
    )

    @Serializable
    data class Parent(
        val element: Element,
    )

    @Serializable
    data class OtherParent(
        val element: OtherElement,
    )

    @Serializable
    data class Root(
        val parent: Parent,
        val otherParent: OtherParent,
    )

    @Test
    fun `xml version 0_9_x test`() {
        val xml = XML {
            indent = 4
        }

        val root = Root(
            parent = Parent(Element("element")),
            otherParent = OtherParent(OtherElement("element")),
        )
        val serialized = xml.encodeToString(root)
        println(serialized)
        val deserialized: Root = XML.decodeFromString(serialized)

        assertEquals(root, deserialized)
    }
}

This will print the following XML:

<Root>
    <Parent>
        <element>
            <a>element</a>
        </element>
    </Parent>
    <OtherParent>
        <element>
            <a>element</a>
        </element>
    </OtherParent>
</Root>

Note how in OtherParent/element the tag is <a>, even though it should be <b>.

hrkfdn avatar Nov 19 '24 15:11 hrkfdn

I've confirmed the issue. It is a caching issue. To get it to work you can disable the cache using (or with whatever policy configuration you use):

XML {
  indent = 4
  defaultPolicy {
      formatCache = FormatCache.Dummy
  }
}

pdvrieze avatar Nov 19 '24 19:11 pdvrieze

I've analysed it. And the key reason is that Element and OtherElement have the same serial name, and as such their types can not be distinguished (and their descriptors are effectively identical). If you instead use @XmlSerialName it will work correctly as that annotation is not transparent. Note that this is a fundamental limitation of the serialization library. Looking at the implementation of PluginGeneratedSerialDescriptor (and the debugger) the serialDescriptors of both are equal (despite the element names being different).

pdvrieze avatar Nov 19 '24 19:11 pdvrieze

This needs "fixing" in the serialization library itself. In the meantime consider that having two types with equal @SerialName annotation in the same serialization context is not supported.

pdvrieze avatar Nov 19 '24 20:11 pdvrieze

Makes sense, thanks for investigating!

hrkfdn avatar Nov 19 '24 20:11 hrkfdn