Merge pull request #1084 from corda/kat-cantDeserialiseChars

Fix to allow classes with char members to deserialize
This commit is contained in:
Katelyn Baker 2017-07-21 13:16:37 +01:00 committed by GitHub
commit e1551fc74e
2 changed files with 55 additions and 4 deletions

View File

@ -55,8 +55,10 @@ sealed class PropertySerializer(val name: String, val readMethod: Method, val re
companion object {
fun make(name: String, readMethod: Method, resolvedType: Type, factory: SerializerFactory): PropertySerializer {
if (SerializerFactory.isPrimitive(resolvedType)) {
// This is a little inefficient for performance since it does a runtime check of type. We could do build time check with lots of subclasses here.
return AMQPPrimitivePropertySerializer(name, readMethod, resolvedType)
return when(resolvedType) {
Char::class.java, Character::class.java -> AMQPCharPropertySerializer(name, readMethod)
else -> AMQPPrimitivePropertySerializer(name, readMethod, resolvedType)
}
} else {
return DescribedTypePropertySerializer(name, readMethod, resolvedType) { factory.get(null, resolvedType) }
}
@ -86,10 +88,9 @@ sealed class PropertySerializer(val name: String, val readMethod: Method, val re
}
/**
* A property serializer for an AMQP primitive type (Int, String, etc).
* A property serializer for most AMQP primitive type (Int, String, etc).
*/
class AMQPPrimitivePropertySerializer(name: String, readMethod: Method, resolvedType: Type) : PropertySerializer(name, readMethod, resolvedType) {
override fun writeClassInfo(output: SerializationOutput) {}
override fun readProperty(obj: Any?, schema: Schema, input: DeserializationInput): Any? {
@ -105,5 +106,21 @@ sealed class PropertySerializer(val name: String, val readMethod: Method, val re
}
}
}
/**
* A property serializer for the AMQP char type, needed as a specialisation as the underlying
* value of the character is stored in numeric UTF-16 form and on deserialisation requires explicit
* casting back to a char otherwise it's treated as an Integer and a TypeMismatch occurs
*/
class AMQPCharPropertySerializer(name: String, readMethod: Method) :
PropertySerializer(name, readMethod, Char::class.java) {
override fun writeClassInfo(output: SerializationOutput) {}
override fun readProperty(obj: Any?, schema: Schema, input: DeserializationInput) = (obj as Int).toChar()
override fun writeProperty(obj: Any?, data: Data, output: SerializationOutput) {
data.putChar((readMethod.invoke(obj) as Char).toInt())
}
}
}

View File

@ -0,0 +1,34 @@
package net.corda.core.serialization.amqp
import org.junit.Test
import java.io.ByteArrayOutputStream
import kotlin.test.assertEquals
/**
* Prior to certain fixes being made within the [PropertySerializaer] classes these simple
* deserialization operations would've blown up with type mismatch errors where the deserlized
* char property of the class would've been treated as an Integer and given to the constructor
* as such
*/
class DeserializeSimpleTypesTests {
@Test
fun testChar() {
data class C(val c: Char)
val c = C('c')
val serialisedC = SerializationOutput().serialize(c)
val deserializedC = DeserializationInput().deserialize(serialisedC)
assertEquals(c.c, deserializedC.c)
}
@Test
fun testCharacter() {
data class C(val c: Character)
val c = C(Character ('c'))
val serialisedC = SerializationOutput().serialize(c)
val deserializedC = DeserializationInput().deserialize(serialisedC)
assertEquals(c.c, deserializedC.c)
}
}