Polymophism with @XmlValue and types with identical tags #341
-
|
I've been trying to represent an EMV XML file that looks like this using the library: <EmvTag tag="77">
<EmvTag tag="9f15">4123</EmvTag>
<EmvTag tag="5f28>840</EmvTag>
</EmvTag>I originally tried building a sealed hierarchy for this: sealed interface Tag {
val tag: String
@Serializable
@SerialName(value = "EmvTag")
data class Primitive(
override val tag: String,
@XmlValue
val value: String,
) : Tag
@Serializable
@SerialName(value = "EmvTag")
data class Constructed(
override val tag: String,
val children: List<Tag>,
) : Tag
}but both types having the same tag seems to break things: I tried adding a custom serializer to work around this: class Serializer : KSerializer<Tag> {
override val descriptor: SerialDescriptor = buildClassSerialDescriptor("Tag")
override fun serialize(encoder: Encoder, value: Tag) {
when (value) {
is Tag.Primitive -> {
encoder.encodeSerializableValue(
serializer = Tag.Primitive.serializer(),
value = value,
)
}
is Tag.Constructed -> {
encoder.encodeSerializableValue(
serializer = Tag.Constructed.serializer(),
value = value,
)
}
}
}
override fun deserialize(decoder: Decoder): Tag {
val xmlDecoder = decoder as? XML.XmlInput ?: error("Serializer only supports XML")
val reader = xmlDecoder.input
return if (isConstructed(reader.getAttributeValue("", "tag") ?: "")) {
Tag.Constructed.serializer().deserialize(decoder)
} else {
Tag.Primitive.serializer().deserialize(decoder)
}
}
private fun isConstructed(tag: String): Boolean =
try {
val firstByte = tag.substring(0, 2).toInt(16)
(firstByte and 0x20) != 0
} catch (_: Exception) {
false
}
}but the lack of a real descriptor broke things again: I tried to add a elements to the descriptor for Finally, I also tried to flatten the data structure into something like this: @Serializable
@SerialName(value = "EmvTag")
data class Tag(
override val tag: String,
val children: List<Tag> = emptyList(),
@XmlValue
val value: String? = null,
) : TagBut this also fails since Is there a supported way to parse something like this where one of the polymorphic subclasses needs to use The manual deserializer: |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 3 replies
-
|
Have a look at These do more or less what you want (except it uses a list). You should probably be able to use |
Beta Was this translation helpful? Give feedback.
Those classes use open polymorphism. In your case you can possibly use sealed polymorphism (or use
XmlSerializerfor special handling of XML content - not unlikeContentPolymorphicSerializerin Json, but it works rather different)