22
33package io.ably.lib.objects
44
5+ import com.fasterxml.jackson.annotation.JsonCreator
56import com.fasterxml.jackson.core.JsonGenerator
67import com.fasterxml.jackson.databind.DeserializationContext
78import com.fasterxml.jackson.databind.ObjectMapper
89import com.fasterxml.jackson.databind.SerializerProvider
10+ import com.fasterxml.jackson.module.paramnames.ParameterNamesModule
911import com.google.gson.*
1012import org.msgpack.core.MessagePack
1113import org.msgpack.core.MessagePacker
1214import org.msgpack.core.MessageUnpacker
1315import org.msgpack.jackson.dataformat.MessagePackFactory
16+ import org.msgpack.value.ImmutableMapValue
1417import java.lang.reflect.Type
1518import java.util.*
1619
@@ -19,7 +22,10 @@ internal val gson: Gson = GsonBuilder().create()
1922
2023// Jackson ObjectMapper for MessagePack serialization (respects @JsonProperty annotations)
2124// Caches type metadata and serializers for ObjectMessage class after first use, so next time it's super fast 🚀
22- private val msgpackMapper = ObjectMapper (MessagePackFactory ())
25+ // https://github.com/FasterXML/jackson-modules-java8/tree/3.x/parameter-names
26+ private val msgpackMapper = ObjectMapper (MessagePackFactory ()).apply {
27+ registerModule(ParameterNamesModule (JsonCreator .Mode .PROPERTIES ))
28+ }
2329
2430internal fun ObjectMessage.toJsonObject (): JsonObject {
2531 return gson.toJsonTree(this ).asJsonObject
@@ -30,29 +36,15 @@ internal fun JsonObject.toObjectMessage(): ObjectMessage {
3036}
3137
3238internal fun ObjectMessage.writeTo (packer : MessagePacker ) {
33- // Jackson automatically creates the correct msgpack map structure
34- val msgpackBytes = msgpackMapper.writeValueAsBytes(this )
35-
36- // Parse the msgpack bytes to get the structured value
37- val tempUnpacker = MessagePack .newDefaultUnpacker(msgpackBytes)
38- val msgpackValue = tempUnpacker.unpackValue()
39- tempUnpacker.close()
40-
41- // Pack the structured value using the provided packer
42- packer.packValue(msgpackValue)
39+ val msgpackBytes = msgpackMapper.writeValueAsBytes(this ) // returns correct msgpack map structure
40+ packer.writePayload(msgpackBytes)
4341}
4442
45- internal fun MessageUnpacker.readObjectMessage (): ObjectMessage {
46- // Read the msgpack value from the unpacker
47- val msgpackValue = this .unpackValue()
48-
49- // Convert the msgpack value back to bytes
50- val tempPacker = MessagePack .newDefaultBufferPacker()
51- tempPacker.packValue(msgpackValue)
52- val msgpackBytes = tempPacker.toByteArray()
53- tempPacker.close()
54-
55- // Let Jackson deserialize the msgpack bytes back to ObjectMessage
43+ internal fun ImmutableMapValue.toObjectMessage (): ObjectMessage {
44+ val msgpackBytes = MessagePack .newDefaultBufferPacker().use { packer ->
45+ packer.packValue(this )
46+ packer.toByteArray()
47+ }
5648 return msgpackMapper.readValue(msgpackBytes, ObjectMessage ::class .java)
5749}
5850
@@ -66,7 +58,7 @@ internal class DefaultLiveObjectSerializer : LiveObjectSerializer {
6658
6759 override fun readMsgpackArray (unpacker : MessageUnpacker ): Array <Any > {
6860 val objectMessagesCount = unpacker.unpackArrayHeader()
69- return Array (objectMessagesCount) { unpacker.readObjectMessage () }
61+ return Array (objectMessagesCount) { unpacker.unpackValue().asMapValue().toObjectMessage () }
7062 }
7163
7264 override fun writeMsgpackArray (objects : Array <out Any >? , packer : MessagePacker ) {
@@ -101,7 +93,7 @@ internal class ObjectDataJsonSerializer : JsonSerializer<ObjectData>, JsonDeseri
10193 when (val v = value.value) {
10294 is Boolean -> obj.addProperty(" boolean" , v)
10395 is String -> obj.addProperty(" string" , v)
104- is Number -> obj.addProperty(" number" , v)
96+ is Number -> obj.addProperty(" number" , v.toDouble() )
10597 is Binary -> obj.addProperty(" bytes" , Base64 .getEncoder().encodeToString(v.data))
10698 // Spec: OD4c5
10799 is JsonObject , is JsonArray -> {
@@ -132,7 +124,7 @@ internal class ObjectDataJsonSerializer : JsonSerializer<ObjectData>, JsonDeseri
132124 )
133125 }
134126 obj.has(" string" ) -> ObjectValue (obj.get(" string" ).asString)
135- obj.has(" number" ) -> ObjectValue (obj.get(" number" ).asNumber )
127+ obj.has(" number" ) -> ObjectValue (obj.get(" number" ).asDouble )
136128 obj.has(" bytes" ) -> ObjectValue (Binary (Base64 .getDecoder().decode(obj.get(" bytes" ).asString)))
137129 else -> throw JsonParseException (" ObjectData must have one of the fields: boolean, string, number, or bytes" )
138130 }
@@ -179,7 +171,7 @@ internal class ObjectDataMsgpackDeserializer : com.fasterxml.jackson.databind.Js
179171 )
180172 }
181173 node.has(" string" ) -> ObjectValue (node.get(" string" ).asText())
182- node.has(" number" ) -> ObjectValue (node.get(" number" ).numberValue ())
174+ node.has(" number" ) -> ObjectValue (node.get(" number" ).doubleValue ())
183175 node.has(" bytes" ) -> ObjectValue (Binary (node.get(" bytes" ).binaryValue()))
184176 else -> throw IllegalArgumentException (" ObjectData must have one of the fields: boolean, string, number, or bytes" )
185177 }
0 commit comments