Grouvie
04/27/2022, 9:39 AM[2,"6bd18013-b33f-43bb-bf91-7745e5517dd2","StatusNotification",{"connectorId":1,"errorCode":"NoError","status":"Available"}]
and
[2,"5a3a42a2-212d-4815-9581-f64ce55fd6cc","Heartbeat",{}]
over websockets to which I then answer:
[3,"6bd18013-b33f-43bb-bf91-7745e5517dd2",{}]
and
[3,"5a3a42a2-212d-4815-9581-f64ce55fd6cc",{"currentTime":"2022-04-27T11:29:38.179938700"}]
.
What is the most elegant way to deserialize, serialize and answer them?Grouvie
04/27/2022, 9:39 AMval request = Json.decodeFromString<JsonArray>(message)
val payload = Call.payload(request)
val response = CallResult.response(request)
@Serializable
data class HeartbeatResponse(
val currentTime: String,
): Response()
@Serializable
class Heartbeat(
): Request()
@Serializable
class Call(
){
companion object {
fun messageType(jsonArray: JsonArray): MessageType {
return MessageType.fromTypeNr(Json.decodeFromJsonElement(jsonArray[0]))
}
private fun action(jsonArray: JsonArray): String {
return Json.decodeFromJsonElement(jsonArray[2])
}
fun payload(jsonArray: JsonArray): Request {
when(ActionType.fromTypeString(action(jsonArray))) {
ActionType.Heartbeat -> {
return Json.decodeFromJsonElement<Heartbeat>(jsonArray[3])
}
}
}
}
}
@Serializable
class CallResult(
){
companion object {
private fun action(jsonArray: JsonArray): String {
return Json.decodeFromJsonElement(jsonArray[2])
}
private fun uniqueId(jsonArray: JsonArray): String {
return Json.decodeFromJsonElement(jsonArray[1])
}
private fun responseMessageType(): JsonElement {
return Json.encodeToJsonElement(MessageType.toTypeNr(MessageType.CALL_RESULT))
}
private fun responseUniqueId(jsonArray: JsonArray): JsonElement {
return Json.encodeToJsonElement(uniqueId(jsonArray))
}
fun response(jsonArray: JsonArray): JsonElement {
return JsonArray(arrayListOf(responseMessageType(), responseUniqueId(jsonArray), payload(jsonArray)))
}
private fun payload(jsonArray: JsonArray): JsonElement {
when(ActionType.fromTypeString(action(jsonArray))) {
ActionType.Heartbeat -> {
return Json.encodeToJsonElement(HeartbeatResponse(LocalDateTime.now().toString()))
}
}
}
}
}
ephemient
04/27/2022, 5:36 PMGrouvie
04/28/2022, 9:25 AMkotlinx.serialization.SerializationException: Class 'Heartbeat' is not registered for polymorphic serialization in the scope of 'RequestPayload'.
Mark the base class as 'sealed' or register the serializer explicitly.
2.
When I add a second subclass to the ResponsePayload I get a type mismatch for the value which I can not resolve.
sealed class ResponsePayload {
@Serializable
@SerialName("Heartbeat")
data class Heartbeat(
val currentTime: String
) : ResponsePayload()
@Serializable
@SerialName("BootNotification")
data class BootNotification(
val bootMessage: String
) : ResponsePayload()
@InternalSerializationApi
object SerializerWithoutDiscriminator : SerializationStrategy<ResponsePayload> {
@OptIn(ExperimentalSerializationApi::class)
override val descriptor: SerialDescriptor = buildSerialDescriptor("ResponsePayload", PolymorphicKind.SEALED)
override fun serialize(encoder: Encoder, value: ResponsePayload) {
val serializer = when (value) {
is Heartbeat -> Heartbeat.serializer()
is BootNotification -> BootNotification.serializer()
else -> throw IllegalStateException("Unknown ResponsePayload")
}
encoder.encodeSerializableValue(serializer, value)
}
}
}
ephemient
04/28/2022, 9:33 AM@SerialName
?
2. with multiple, the serializer types are narrower. try
when (value) {
is Heartbeat -> encoder.encodeSerializableValue(Heartbeat.serializer(), value)
is BootNotification -> encoder.encodeSerializableValue(BootNotification.serializer() value)
or performing an unchecked castGrouvie
04/28/2022, 9:35 AM@Serializable
sealed class RequestPayload {
@Serializable
@SerialName("Heartbeat")
object Heartbeat : RequestPayload()
}
I used this.ephemient
04/28/2022, 10:08 AMval serializer = decoder.serializersModule.getPolymorphic(baseClass, serializedClassName.jsonPrimitive.content)
?: (baseClass.serializerOrNull() as? AbstractPolymorphicSerializer<T>)
?.findPolymorphicSerializerOrNull(decoder, serializedClassName.jsonPrimitive.content)
?: throw SerializationException(
but I feel like there should be a better way that doesn't require on library internals, I just don't know of itGrouvie
04/28/2022, 11:02 AMGrouvie
04/28/2022, 11:03 AM