(Not Kord) Deserialize JSON with unordered fields (Kotlin Serialization)
Hello
I have this deserialization function from my custom Serializer:
When the JSON is:
That works perfectly.
But when the json is:
The exception
is there a way to support unordered fields?
I have this deserialization function from my custom Serializer:
override fun deserialize(decoder: Decoder): PacketWrapper {
return decoder.decodeStructure(descriptor) {
var type: Byte? = null
var data: Packet? = null
if(decodeSequentially()) {
type = decodeByteElement(descriptor, 0)
val serializer = typeToPacket[type] ?: throw SerializationException("The field 'type' is required")
data = decodeSerializableElement(descriptor, 1, serializer)
PacketWrapper(data)
} else {
loop@ while (true) {
when (val index = decodeElementIndex(descriptor)) {
0 -> type = decodeByteElement(descriptor, index)
1 -> {
val serializer = typeToPacket[type] ?: throw SerializationException("The field 'type' is required")
data = decodeSerializableElement(descriptor, index, serializer as KSerializer<Packet>)
}
CompositeDecoder.DECODE_DONE -> break@loop
else -> throw SerializationException("Unexpected index: $index")
}
}
type ?: throw SerializationException("The field 'type' is required")
data ?: throw SerializationException("The field 'data' is required")
PacketWrapper(data)
}
}
}override fun deserialize(decoder: Decoder): PacketWrapper {
return decoder.decodeStructure(descriptor) {
var type: Byte? = null
var data: Packet? = null
if(decodeSequentially()) {
type = decodeByteElement(descriptor, 0)
val serializer = typeToPacket[type] ?: throw SerializationException("The field 'type' is required")
data = decodeSerializableElement(descriptor, 1, serializer)
PacketWrapper(data)
} else {
loop@ while (true) {
when (val index = decodeElementIndex(descriptor)) {
0 -> type = decodeByteElement(descriptor, index)
1 -> {
val serializer = typeToPacket[type] ?: throw SerializationException("The field 'type' is required")
data = decodeSerializableElement(descriptor, index, serializer as KSerializer<Packet>)
}
CompositeDecoder.DECODE_DONE -> break@loop
else -> throw SerializationException("Unexpected index: $index")
}
}
type ?: throw SerializationException("The field 'type' is required")
data ?: throw SerializationException("The field 'data' is required")
PacketWrapper(data)
}
}
}When the JSON is:
{"type":0,"data":{"message":"Hello, World!"}}{"type":0,"data":{"message":"Hello, World!"}}That works perfectly.
But when the json is:
{"data":{"message":"Hello, World!"},"type":0}{"data":{"message":"Hello, World!"},"type":0}The exception
The field 'type' is requiredThe field 'type' is required (from the loop) is thrown.is there a way to support unordered fields?
Solution
@Serializable
sealed interface Packet {
val data: Data
interface Data
}
@Serializable
@SerialName("hello")
data class HelloPacket(override val data: Data) : Packet {
@Serializable
data class Data(val pingInterval: Int) : Packet.Data
}@Serializable
sealed interface Packet {
val data: Data
interface Data
}
@Serializable
@SerialName("hello")
data class HelloPacket(override val data: Data) : Packet {
@Serializable
data class Data(val pingInterval: Int) : Packet.Data
}