pdvrieze / xmlutil

XML Serialization library for Kotlin
https://pdvrieze.github.io/xmlutil/
Apache License 2.0
377 stars 30 forks source link

Cannot force a property to be deserialized as an attribute via `@XmlElement(false)` #224

Closed sschuberth closed 3 months ago

sschuberth commented 3 months ago

I have two simple classes like

/**
 * The minimal manifest structure as used by the wrapping "manifest.xml" file as of repo version 2.4. For the full
 * structure see https://gerrit.googlesource.com/git-repo/+/refs/heads/master/docs/manifest-format.md.
 */
@Serializable
private data class Manifest(
    @XmlElement(false)
    val include: Include
)

/**
 * The "include" tag of a "manifest.xml" file, see
 * https://gerrit.googlesource.com/git-repo/+/refs/heads/master/docs/manifest-format.md#Element-include.
 */
@Serializable
private data class Include(
    val name: String
)

val xml = XML()
xml.decodeFromString<Manifest>(manifestWrapper.readText())

My understanding of this is that Manifest.include should be (de-)serialized as an attribute (not an element) due to my @XmlElement(false) annotation, but I'm getting

nl.adaptivity.xmlutil.serialization.UnknownXmlFieldException: Could not find a field for name (org.ossreviewtoolkit.plugins.versioncontrolsystems.git.Manifest) manifest/include (Element)
  candidates: Include (Element) at position 13:34

So include is being looked up as an element, which causes the name to be derived from the type instead of the property name, and also the wrong name ("Include" instead of "include") to be used.

Is my understanding of how things are supposed to work wrong?

pdvrieze commented 3 months ago

The reason is that a (non-value) class can not be a text value. While it is possible to use the policy to force a single-element class to be interpreted as a value class this is not currently implemented. Of course you can create your own policy (extending the default one or not) that does so.

sschuberth commented 3 months ago

Ah, I keep forgetting about Kotlin's value classes. So the proper solution would be to simply switch my data classes to these?

sschuberth commented 3 months ago

Sorry, I was completely mislead here. In my case "include" actually is a tag in the original XML file, not an attribute. So the initially described use-case is invalid.