Skip to content

Commit ad10253

Browse files
sacOO7claude
andcommitted
Retarget path-based serializers to WireObjectMessage model
Point the JSON and MsgPack serializers in io.ably.lib.object.serialization at the new WireObjectMessage wire model instead of the legacy io.ably.lib.objects.ObjectMessage, so the new `object` package has no dependency on the legacy `objects` package. - DefaultSerialization: implement the new ObjectSerializer interface and (de)serialize WireObjectMessage arrays (reflectively loaded via ObjectSerializer.Holder). - Json/MsgpackSerialization: bind the Wire* types; replace legacy objectError with the object package's objectStateError (same 500/92000). - WireObjectMessage: restore the gson annotations required for wire-format fidelity - @SerializedName("object") on objectState and @JsonAdapter(WireObjectDataJsonSerializer) on WireObjectData. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 5e452c2 commit ad10253

4 files changed

Lines changed: 152 additions & 150 deletions

File tree

liveobjects/src/main/kotlin/io/ably/lib/object/message/WireObjectMessage.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ package io.ably.lib.`object`.message
33
import com.google.gson.Gson
44
import com.google.gson.JsonElement
55
import com.google.gson.JsonObject
6+
import com.google.gson.annotations.JsonAdapter
7+
import com.google.gson.annotations.SerializedName
8+
import io.ably.lib.`object`.serialization.WireObjectDataJsonSerializer
69
import java.nio.charset.StandardCharsets
710
import java.util.Base64
811

@@ -36,6 +39,7 @@ internal enum class WireObjectsMapSemantics(val code: Int) {
3639
}
3740

3841
/** Spec: OD1, OD2 - binary carried as base64 string on the wire */
42+
@JsonAdapter(WireObjectDataJsonSerializer::class)
3943
internal data class WireObjectData(
4044
val objectId: String? = null, // OD2a
4145
val string: String? = null, // OD2f
@@ -145,6 +149,7 @@ internal data class WireObjectMessage(
145149
val connectionId: String? = null, // OM2c
146150
val extras: JsonObject? = null, // OM2d
147151
val operation: WireObjectOperation? = null, // OM2f
152+
@SerializedName("object")
148153
val objectState: WireObjectState? = null, // OM2g - wire key "object"
149154
val serial: String? = null, // OM2h
150155
val serialTimestamp: Long? = null, // OM2j

liveobjects/src/main/kotlin/io/ably/lib/object/serialization/DefaultSerialization.kt

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,25 @@
11
package io.ably.lib.`object`.serialization
22

33
import com.google.gson.*
4-
import io.ably.lib.objects.*
5-
6-
import io.ably.lib.objects.ObjectMessage
4+
import io.ably.lib.`object`.message.WireObjectMessage
75
import org.msgpack.core.MessagePacker
86
import org.msgpack.core.MessageUnpacker
97

108
/**
11-
* Default implementation of {@link ObjectsSerializer} that handles serialization/deserialization
12-
* of ObjectMessage arrays for both JSON and MessagePack formats using Jackson and Gson.
13-
* Dynamically loaded by ObjectsHelper#getSerializer() to avoid hard dependencies.
9+
* Default implementation of {@link ObjectSerializer} that handles serialization/deserialization
10+
* of WireObjectMessage arrays for both JSON and MessagePack formats using Gson and MessagePack.
11+
* Dynamically loaded by ObjectSerializer#tryGet() to avoid hard dependencies.
1412
*/
15-
@Suppress("unused") // Used via reflection in ObjectsHelper
16-
internal class DefaultObjectsSerializer : ObjectsSerializer {
13+
@Suppress("unused") // Used via reflection in ObjectSerializer.Holder
14+
internal class DefaultObjectsSerializer : ObjectSerializer {
1715

1816
override fun readMsgpackArray(unpacker: MessageUnpacker): Array<Any> {
1917
val objectMessagesCount = unpacker.unpackArrayHeader()
2018
return Array(objectMessagesCount) { readObjectMessage(unpacker) }
2119
}
2220

2321
override fun writeMsgpackArray(objects: Array<out Any>, packer: MessagePacker) {
24-
val objectMessages = objects.map { it as ObjectMessage }
22+
val objectMessages = objects.map { it as WireObjectMessage }
2523
packer.packArrayHeader(objectMessages.size)
2624
objectMessages.forEach { it.writeMsgpack(packer) }
2725
}
@@ -34,7 +32,7 @@ internal class DefaultObjectsSerializer : ObjectsSerializer {
3432
}
3533

3634
override fun asJsonArray(objects: Array<out Any>): JsonArray {
37-
val objectMessages = objects.map { it as ObjectMessage }
35+
val objectMessages = objects.map { it as WireObjectMessage }
3836
val jsonArray = JsonArray()
3937
for (objectMessage in objectMessages) {
4038
jsonArray.add(objectMessage.toJsonObject())

liveobjects/src/main/kotlin/io/ably/lib/object/serialization/JsonSerialization.kt

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,25 @@
11
package io.ably.lib.`object`.serialization
22

33
import com.google.gson.*
4-
import io.ably.lib.objects.ObjectsMapSemantics
5-
import io.ably.lib.objects.ObjectData
6-
import io.ably.lib.objects.ObjectMessage
7-
import io.ably.lib.objects.ObjectOperationAction
8-
import io.ably.lib.objects.serialization.EnumCodeTypeAdapter
4+
import io.ably.lib.`object`.message.WireObjectData
5+
import io.ably.lib.`object`.message.WireObjectMessage
6+
import io.ably.lib.`object`.message.WireObjectOperationAction
7+
import io.ably.lib.`object`.message.WireObjectsMapSemantics
98
import java.lang.reflect.Type
109
import kotlin.enums.EnumEntries
1110

1211
// Gson instance for JSON serialization/deserialization
1312
internal val gson = GsonBuilder()
14-
.registerTypeAdapter(ObjectOperationAction::class.java, EnumCodeTypeAdapter({ it.code }, ObjectOperationAction.entries))
15-
.registerTypeAdapter(ObjectsMapSemantics::class.java, EnumCodeTypeAdapter({ it.code }, ObjectsMapSemantics.entries))
13+
.registerTypeAdapter(WireObjectOperationAction::class.java, EnumCodeTypeAdapter({ it.code }, WireObjectOperationAction.entries))
14+
.registerTypeAdapter(WireObjectsMapSemantics::class.java, EnumCodeTypeAdapter({ it.code }, WireObjectsMapSemantics.entries))
1615
.create()
1716

18-
internal fun ObjectMessage.toJsonObject(): JsonObject {
17+
internal fun WireObjectMessage.toJsonObject(): JsonObject {
1918
return gson.toJsonTree(this).asJsonObject
2019
}
2120

22-
internal fun JsonObject.toObjectMessage(): ObjectMessage {
23-
return gson.fromJson(this, ObjectMessage::class.java)
21+
internal fun JsonObject.toObjectMessage(): WireObjectMessage {
22+
return gson.fromJson(this, WireObjectMessage::class.java)
2423
}
2524

2625
internal class EnumCodeTypeAdapter<T : Enum<T>>(
@@ -39,8 +38,8 @@ internal class EnumCodeTypeAdapter<T : Enum<T>>(
3938
}
4039
}
4140

42-
internal class ObjectDataJsonSerializer : JsonSerializer<ObjectData>, JsonDeserializer<ObjectData> {
43-
override fun serialize(src: ObjectData, typeOfSrc: Type?, context: JsonSerializationContext?): JsonElement {
41+
internal class WireObjectDataJsonSerializer : JsonSerializer<WireObjectData>, JsonDeserializer<WireObjectData> {
42+
override fun serialize(src: WireObjectData, typeOfSrc: Type?, context: JsonSerializationContext?): JsonElement {
4443
val obj = JsonObject()
4544
src.objectId?.let { obj.addProperty("objectId", it) }
4645
src.string?.let { obj.addProperty("string", it) }
@@ -51,7 +50,7 @@ internal class ObjectDataJsonSerializer : JsonSerializer<ObjectData>, JsonDeseri
5150
return obj
5251
}
5352

54-
override fun deserialize(json: JsonElement, typeOfT: Type?, context: JsonDeserializationContext?): ObjectData {
53+
override fun deserialize(json: JsonElement, typeOfT: Type?, context: JsonDeserializationContext?): WireObjectData {
5554
val obj = if (json.isJsonObject) json.asJsonObject else throw JsonParseException("Expected JsonObject")
5655
val objectId = if (obj.has("objectId")) obj.get("objectId").asString else null
5756
val string = if (obj.has("string")) obj.get("string").asString else null
@@ -63,6 +62,6 @@ internal class ObjectDataJsonSerializer : JsonSerializer<ObjectData>, JsonDeseri
6362
if (objectId == null && string == null && number == null && boolean == null && bytes == null && json == null) {
6463
throw JsonParseException("Since objectId is not present, at least one of the value fields must be present")
6564
}
66-
return ObjectData(objectId = objectId, string = string, number = number, boolean = boolean, bytes = bytes, json = json)
65+
return WireObjectData(objectId = objectId, string = string, number = number, boolean = boolean, bytes = bytes, json = json)
6766
}
6867
}

0 commit comments

Comments
 (0)