Skip to content

Commit

Permalink
Provide an available KotlinXJsonConverter, since the kotlinx.serializ…
Browse files Browse the repository at this point in the history
…ation is multiplatform and requires inline reified functions, which aren't compatible with a generic interface or abstract class
  • Loading branch information
jayohms committed Aug 10, 2023
1 parent 9d47d40 commit 7603568
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 15 deletions.
6 changes: 1 addition & 5 deletions strada/src/main/kotlin/dev/hotwire/strada/BridgeComponent.kt
Original file line number Diff line number Diff line change
Expand Up @@ -95,11 +95,7 @@ abstract class BridgeComponent<in D : BridgeDestination>(
* reply will be ignored.
*/
inline fun <reified T> 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 {
Expand Down
12 changes: 2 additions & 10 deletions strada/src/main/kotlin/dev/hotwire/strada/Message.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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 <reified T> 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)
}
}

Expand Down
57 changes: 57 additions & 0 deletions strada/src/main/kotlin/dev/hotwire/strada/StradaJsonConverter.kt
Original file line number Diff line number Diff line change
@@ -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 <reified T> toObject(jsonData: String): T? {
val converter = requireNotNull(Strada.config.jsonConverter) { NO_CONVERTER }

return when (converter) {
is KotlinXJsonConverter -> converter.toObject<T>(jsonData)
is StradaJsonTypeConverter -> converter.toObject(jsonData, T::class.java)
else -> throw IllegalStateException(INVALID_CONVERTER)
}
}

inline fun <reified T> 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 <T> toObject(jsonData: String, type: Class<T>): T?
abstract fun <T> toJson(data: T, type: Class<T>): String
}

class KotlinXJsonConverter : StradaJsonConverter() {
val json = Json { ignoreUnknownKeys = true }

inline fun <reified T> toObject(jsonData: String): T? {
return try {
json.decodeFromString(jsonData)
} catch(e: Exception) {
logException(e)
null
}
}

inline fun <reified T> toJson(data: T): String {
return json.encodeToString(data)
}

fun logException(e: Exception) {
logEvent("kotlinXJsonConverterFailedWithError", e.toString())
}
}

0 comments on commit 7603568

Please sign in to comment.