diff --git a/README.md b/README.md index 72d491b..68c0080 100644 --- a/README.md +++ b/README.md @@ -58,12 +58,8 @@ socket.connect() // or internal reconnect logic kicks in ``` -You can also inject your own OkHttp Client and GSON into the Socket to provide your own configuration +You can also inject your own OkHttp Client into the Socket to provide your own configuration ```kotlin - -// Configure your own GSON instance -val gson = Gson.Builder().create() - // Configure your own OkHttp Client val client = OkHttpClient.Builder() .connectTimeout(1000, TimeUnit.MILLISECONDS) @@ -72,14 +68,37 @@ val client = OkHttpClient.Builder() // Create Socket with your custom instances val params = hashMapOf("token" to "abc123") val socket = Socket("http://localhost:4000/socket/websocket", - params, - gson, - client) + params, + client) +``` + +By default, the client use GSON to encode and decode JSON. If you prefer to manage this yourself, you +can provide custom encode/decode functions in the `Socket` constructor. + +```kotlin + +// Configure your own GSON instance +val gson = Gson.Builder().create() +val encoder: EncodeClosure = { + // Encode a Map into JSON using your custom GSON instance or another JSON library + // of your choice (Moshi, etc) +} +val decoder: DecodeClosure = { + // Decode a JSON String into a `Message` object using your custom JSON library +} + +// Create Socket with your custom instances +val params = hashMapOf("token" to "abc123") +val socket = Socket("http://localhost:4000/socket/websocket", + params, + encoder, + decoder) ``` + ### Installation JavaPhoenixClient is hosted on MavenCentral. You'll need to make sure you declare `mavenCentral()` as one of your repositories diff --git a/src/main/kotlin/org/phoenixframework/Defaults.kt b/src/main/kotlin/org/phoenixframework/Defaults.kt index f410354..ea56702 100644 --- a/src/main/kotlin/org/phoenixframework/Defaults.kt +++ b/src/main/kotlin/org/phoenixframework/Defaults.kt @@ -55,6 +55,22 @@ object Defaults { .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES) .create() + /** + * Default JSON decoder, backed by GSON, that takes JSON and converts it + * into a Message object. + */ + val decode: DecodeClosure = { rawMessage -> + gson.fromJson(rawMessage, Message::class.java) + } + + /** + * Default JSON encoder, backed by GSON, that takes a Map and + * converts it into a JSON String. + */ + val encode: EncodeClosure = { payload -> + gson.toJson(payload) + } + /** * Takes an endpoint and a params closure given by the User and constructs a URL that * is ready to be sent to the Socket connection. diff --git a/src/main/kotlin/org/phoenixframework/Socket.kt b/src/main/kotlin/org/phoenixframework/Socket.kt index be32a22..7edf45f 100644 --- a/src/main/kotlin/org/phoenixframework/Socket.kt +++ b/src/main/kotlin/org/phoenixframework/Socket.kt @@ -104,6 +104,13 @@ const val WS_CLOSE_ABNORMAL = 1006 */ typealias PayloadClosure = () -> Payload? +/** A closure that will encode a Map into a JSON String */ +typealias EncodeClosure = (Map) -> String + +/** A closure that will decode a JSON String into a [Message] */ +typealias DecodeClosure = (String) -> Message + + /** * Connects to a Phoenix Server */ @@ -118,13 +125,15 @@ typealias PayloadClosure = () -> Payload? * ``` * @param url Url to connect to such as https://example.com/socket * @param paramsClosure Closure which allows to change parameters sent during connection. - * @param gson Default GSON Client to parse JSON. You can provide your own if needed. + * @param encode Optional. Provide a custom JSON encoding implementation + * @param decode Optional. Provide a custom JSON decoding implementation * @param client Default OkHttpClient to connect with. You can provide your own if needed. */ class Socket( url: String, val paramsClosure: PayloadClosure, - private val gson: Gson = Defaults.gson, + private val encode: EncodeClosure = Defaults.encode, + private val decode: DecodeClosure = Defaults.decode, private val client: OkHttpClient = OkHttpClient.Builder().build() ) { @@ -226,15 +235,17 @@ class Socket( * * @param url Url to connect to such as https://example.com/socket * @param params Constant parameters to send when connecting. Defaults to null - * @param gson Default GSON Client to parse JSON. You can provide your own if needed. + * @param encode Optional. Provide a custom JSON encoding implementation + * @param decode Optional. Provide a custom JSON decoding implementation * @param client Default OkHttpClient to connect with. You can provide your own if needed. */ constructor( url: String, params: Payload? = null, - gson: Gson = Defaults.gson, + encode: EncodeClosure = Defaults.encode, + decode: DecodeClosure = Defaults.decode, client: OkHttpClient = OkHttpClient.Builder().build() - ) : this(url, { params }, gson, client) + ) : this(url, { params }, encode, decode, client) init { var mutableUrl = url @@ -387,7 +398,7 @@ class Socket( ref?.let { body["ref"] = it } joinRef?.let { body["join_ref"] = it } - val data = gson.toJson(body) + val data = this.encode(body) connection?.let { transport -> this.logItems("Push: Sending $data") transport.send(data) @@ -569,7 +580,7 @@ class Socket( this.logItems("Receive: $rawMessage") // Parse the message as JSON - val message = gson.fromJson(rawMessage, Message::class.java) + val message = this.decode(rawMessage) // Clear heartbeat ref, preventing a heartbeat timeout disconnect if (message.ref == pendingHeartbeatRef) pendingHeartbeatRef = null