From 7603568d31d9bf55f84a5d4843ff458540402b86 Mon Sep 17 00:00:00 2001 From: Jay Ohms Date: Thu, 10 Aug 2023 09:47:09 -0400 Subject: [PATCH] Provide an available KotlinXJsonConverter, since the kotlinx.serialization is multiplatform and requires inline reified functions, which aren't compatible with a generic interface or abstract class --- .../dev/hotwire/strada/BridgeComponent.kt | 6 +- .../main/kotlin/dev/hotwire/strada/Message.kt | 12 +--- .../dev/hotwire/strada/StradaJsonConverter.kt | 57 +++++++++++++++++++ 3 files changed, 60 insertions(+), 15 deletions(-) diff --git a/strada/src/main/kotlin/dev/hotwire/strada/BridgeComponent.kt b/strada/src/main/kotlin/dev/hotwire/strada/BridgeComponent.kt index 680af23..39fdbe3 100644 --- a/strada/src/main/kotlin/dev/hotwire/strada/BridgeComponent.kt +++ b/strada/src/main/kotlin/dev/hotwire/strada/BridgeComponent.kt @@ -95,11 +95,7 @@ abstract class BridgeComponent( * reply will be ignored. */ inline fun replyTo(event: String, data: T): Boolean { - val converter = requireNotNull(Strada.config.jsonConverter) { - "A Strada.config.jsonConverter must be set to encode data" - } - - return replyTo(event, jsonData = converter.toJson(data, T::class.java)) + return replyTo(event, jsonData = StradaJsonConverter.toJson(data)) } private fun reply(message: Message): Boolean { diff --git a/strada/src/main/kotlin/dev/hotwire/strada/Message.kt b/strada/src/main/kotlin/dev/hotwire/strada/Message.kt index 7935ff9..9ec2013 100644 --- a/strada/src/main/kotlin/dev/hotwire/strada/Message.kt +++ b/strada/src/main/kotlin/dev/hotwire/strada/Message.kt @@ -48,19 +48,11 @@ data class Message internal constructor( event: String = this.event, data: T ): Message { - val converter = requireNotNull(Strada.config.jsonConverter) { - "A Strada.config.jsonConverter must be set to encode json" - } - - return replacing(event, converter.toJson(data, T::class.java)) + return replacing(event, StradaJsonConverter.toJson(data)) } inline fun data(): T? { - val converter = requireNotNull(Strada.config.jsonConverter) { - "A Strada.config.jsonConverter must be set to decode json" - } - - return converter.toObject(jsonData, T::class.java) + return StradaJsonConverter.toObject(jsonData) } } diff --git a/strada/src/main/kotlin/dev/hotwire/strada/StradaJsonConverter.kt b/strada/src/main/kotlin/dev/hotwire/strada/StradaJsonConverter.kt index 9679918..b728960 100644 --- a/strada/src/main/kotlin/dev/hotwire/strada/StradaJsonConverter.kt +++ b/strada/src/main/kotlin/dev/hotwire/strada/StradaJsonConverter.kt @@ -1,6 +1,63 @@ package dev.hotwire.strada +import kotlinx.serialization.decodeFromString +import kotlinx.serialization.encodeToString +import kotlinx.serialization.json.Json +import java.lang.Exception + abstract class StradaJsonConverter { + companion object { + const val NO_CONVERTER = + "A Strada.config.jsonConverter must be set to encode or decode json" + + const val INVALID_CONVERTER = + "The configured json converter must be a StradaJsonTypeConverter " + + "or use the provided KotlinXJsonConverter." + + inline fun toObject(jsonData: String): T? { + val converter = requireNotNull(Strada.config.jsonConverter) { NO_CONVERTER } + + return when (converter) { + is KotlinXJsonConverter -> converter.toObject(jsonData) + is StradaJsonTypeConverter -> converter.toObject(jsonData, T::class.java) + else -> throw IllegalStateException(INVALID_CONVERTER) + } + } + + inline fun toJson(data: T): String { + val converter = requireNotNull(Strada.config.jsonConverter) { NO_CONVERTER } + + return when (converter) { + is KotlinXJsonConverter -> converter.toJson(data) + is StradaJsonTypeConverter -> converter.toJson(data, T::class.java) + else -> throw IllegalStateException(INVALID_CONVERTER) + } + } + } +} + +abstract class StradaJsonTypeConverter : StradaJsonConverter() { abstract fun toObject(jsonData: String, type: Class): T? abstract fun toJson(data: T, type: Class): String } + +class KotlinXJsonConverter : StradaJsonConverter() { + val json = Json { ignoreUnknownKeys = true } + + inline fun toObject(jsonData: String): T? { + return try { + json.decodeFromString(jsonData) + } catch(e: Exception) { + logException(e) + null + } + } + + inline fun toJson(data: T): String { + return json.encodeToString(data) + } + + fun logException(e: Exception) { + logEvent("kotlinXJsonConverterFailedWithError", e.toString()) + } +}