I use <@U0YD63XDY> Xml lib and I want to deseriali...
# serialization
h
I use @pdvrieze Xml lib and I want to deserialize this xml code
Copy code
<?xml version="1.0" encoding="UTF-8" ?>
<documentation>
    <foo>A</foo>
    bar
</documentation>
How do I declare the class to get
bar
?
p
@hfhbd What you are dealing with is what XML calls mixed content. There is a test case that does this that should give you an example. Note that it depends a bit on the mode configured: https://github.com/pdvrieze/xmlutil/blob/master/serialization/src/commonTest/kotlin/nl/adaptivity/xml/serialization/MixedValueContainerTest.kt
There are other ways (eg. using
CompactFragment
), but I don't think that an inline value class to the string works (it might, I don't remember testing/implementing that - the challenge is that this needs a special case in deserialization)
h
Thank you for the fast answer, but I still don't get it to work.
Copy code
@Serializable
data class Documentation(
    @XmlValue
    val elements: List<@Polymorphic Any>,
) {
    companion object {
        fun module() = SerializersModule {
            polymorphic(Any::class, String::class, String.serializer())
            polymorphic(Any::class, Foo::class, Foo.serializer())
        }
    }
}

@Serializable
@XmlSerialName("foo")
private data class Foo(
    val a: String
)

fun main() {
    val x = XML(serializersModule = Test.module()).decodeFromString(
        Documentation.serializer(), myFile
    )
    println(x)
}
What do I miss?
p
@hfhbd I'm not sure, what kind of error messages do you get? (I see one error in the code, the module to use should be from
Documentation
not
Test
- this could be a copy-paste-edit problem though)
Other one, you need to enable autopolymorphic serialization (the tests do this automatically). (This is part of creating the format)
h
Thank you, it finally worked. BTW is it expected the code does only work with
autoPolymorphic = true
, but not with
recommended()
?
Copy code
fun main() {
    //language=xml
    val xml = """
        <?xml version="1.0" encoding="UTF-8" ?>
        <MixedValueContainer>
            foo
            <address houseNumber="10" street="Downing Street" city="London"/>
            bar
        </MixedValueContainer>
    """.trimIndent()
    val x = XML(SerializersModule {
        include(MixedValueContainer.serializerModule())
    }) {
        autoPolymorphic = true
        // recommended()
    }.decodeFromString(
        MixedValueContainer.serializer(), xml
    )
    println(x)
}

@Serializable
@XmlSerialName("address")
data class Address(
    val houseNumber: String,
    val street: String,
    val city: String,
)

@Serializable
data class MixedValueContainer(
    @XmlValue
    val data: List<@Polymorphic Any>
) {
    companion object {
        fun serializerModule() = SerializersModule {
            polymorphic(Any::class, String::class, String.serializer())
            polymorphic(Any::class, Address::class, Address.serializer())
        }
    }
}
p
Recommended is intended to include autoPolymorphic, but it might be broken in the way it works (darn legacy API support). But autoPolymorphic is required. Without autopolymorphic each polymorphic value is serialized the "default" kotlinx.serialization way with a wrapper that holds the type and value. That will not support pure text content (obviously) and doesn't look like "normal" XML. What I do notice is that it is actually never valid to use non-auto-polymorphic with
@XmlValue
for some types (primitives could work)