Skip to content

Commit

Permalink
fix: handle decoding nested class with missing keys and ignoreUnkownKeys
Browse files Browse the repository at this point in the history
  • Loading branch information
Stew-Boling-Sense authored and esensar committed Oct 23, 2022
1 parent 213ee5e commit a9c3082
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,15 @@ internal class BasicMsgPackDecoder(
val inlineDecoders: Map<SerialDescriptor, (InlineDecoderHelper) -> Decoder> = mapOf()
) : AbstractDecoder(), MsgPackTypeDecoder {

private val depthStack: ArrayDeque<Unit> = ArrayDeque()

override fun decodeElementIndex(descriptor: SerialDescriptor): Int {
if (descriptor.kind in arrayOf(StructureKind.CLASS, StructureKind.OBJECT)) {
val next = dataBuffer.peekSafely()
if (next != null && MsgPackType.String.isString(next)) {
val fieldName = kotlin.runCatching { decodeString() }.getOrNull() ?: return CompositeDecoder.UNKNOWN_NAME
val index = descriptor.getElementIndex(fieldName)
return if (index == CompositeDecoder.UNKNOWN_NAME && configuration.ignoreUnknownKeys) {
return if (index == CompositeDecoder.UNKNOWN_NAME && configuration.ignoreUnknownKeys && depthStack.isEmpty()) {
MsgPackNullableDynamicSerializer.deserialize(this)
decodeElementIndex(descriptor)
} else {
Expand Down Expand Up @@ -181,13 +183,20 @@ internal class BasicMsgPackDecoder(
if (descriptor.serialName == "com.ensarsarajcic.kotlinx.serialization.msgpack.extensions.MsgPackExtension") {
return ExtensionTypeDecoder(this)
}

depthStack.addFirst(Unit)
// Handle extension types as arrays
val size = decodeCollectionSize(descriptor)
return ClassMsgPackDecoder(this, size)
}
return this
}

override fun endStructure(descriptor: SerialDescriptor) {
super.endStructure(descriptor)
depthStack.removeFirstOrNull()
}

override fun peekNextType(): Byte {
return dataBuffer.peek()
}
Expand All @@ -211,7 +220,12 @@ internal class ClassMsgPackDecoder(
if (decodedElements >= size) return CompositeDecoder.DECODE_DONE
val result = basicMsgPackDecoder.decodeElementIndex(descriptor)
if (result != CompositeDecoder.DECODE_DONE) decodedElements++
return result
return if (result == CompositeDecoder.UNKNOWN_NAME) {
MsgPackNullableDynamicSerializer.deserialize(this)
decodeElementIndex(descriptor)
} else {
result
}
}

override fun decodeSequentially(): Boolean = false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,15 @@ internal class MsgPackDecoderTest {
}
}

@Test
fun testSampleClassWithNestedValueAndMissingKeys() {
TestData.nestedSampleClassWithMissingValue.forEach { (input, result) ->
val decoder = BasicMsgPackDecoder(MsgPackConfiguration.default, SerializersModule {}, input.hexStringToByteArray().toMsgPackBuffer())
val serializer = TestData.SampleClassWithNestedClass.serializer()
assertEquals(result, serializer.deserialize(decoder))
}
}

@Test
fun testTimestampDecode() {
TestData.timestampTestPairs.forEach { (input, result) ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,19 @@ object TestData {
val testBoolean: Boolean
)

@Serializable
data class SampleClassWithNestedClass(
val testString: String,
val testInt: Int,
val testBoolean: Boolean,
val testNested: NestedClass
) {
@Serializable
data class NestedClass(
val testInt: Int? = null
)
}

val sampleClassTestPairs = arrayOf(
"83aa74657374537472696e67a3646566a774657374496e747bab74657374426f6f6c65616ec3" to SampleClass("def", 123, true)
)
Expand All @@ -169,6 +182,9 @@ object TestData {
val triplesTestPairs: Array<Pair<String, Triple<String, String, String>>> = arrayOf(
"83a56669727374a5416c696365a67365636f6e64a3426f62a57468697264a454657374" to Triple("Alice", "Bob", "Test")
)
val nestedSampleClassWithMissingValue = arrayOf(
"84aa74657374537472696e67a3646566a774657374496e747bab74657374426f6f6c65616ec3aa746573744e657374656482aa74657374537472696e67a3646566ab74657374426f6f6c65616ec3" to SampleClassWithNestedClass("def", 123, true, SampleClassWithNestedClass.NestedClass(null))
)
}

@Serializable
Expand Down

0 comments on commit a9c3082

Please sign in to comment.