Skip to content

Commit 5d82155

Browse files
committed
Using json serializer v2
1 parent 940d9dd commit 5d82155

File tree

10 files changed

+102
-102
lines changed

10 files changed

+102
-102
lines changed

ChatExample/app/build.gradle

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@ apply plugin: 'kotlin-android'
55
apply plugin: 'kotlin-android-extensions'
66

77
android {
8-
compileSdkVersion 28
8+
compileSdkVersion 30
99
defaultConfig {
1010
applicationId "com.github.dsrees.chatexample"
1111
minSdkVersion 19
12-
targetSdkVersion 28
12+
targetSdkVersion 30
1313
versionCode 1
1414
versionName "1.0"
1515
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
@@ -36,8 +36,8 @@ dependencies {
3636
`/build/lib/*.jar` to `/ChatExample/app/libs`
3737
and comment out the mavenCentral() dependency
3838
*/
39-
// implementation fileTree(dir: 'libs', include: ['*.jar'])
40-
implementation 'com.github.dsrees:JavaPhoenixClient:0.3.4'
39+
implementation fileTree(dir: 'libs', include: ['*.jar'])
40+
// implementation 'com.github.dsrees:JavaPhoenixClient:0.3.4'
4141

4242

4343
implementation "com.google.code.gson:gson:2.8.5"

src/main/kotlin/org/phoenixframework/Channel.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ class Channel(
224224

225225
// Perform when the join reply is received
226226
this.on(Event.REPLY) { message ->
227-
this.trigger(replyEventName(message.ref), message.payload, message.ref, message.joinRef)
227+
this.trigger(replyEventName(message.ref), message.rawPayload, message.ref, message.joinRef)
228228
}
229229
}
230230

@@ -394,7 +394,7 @@ class Channel(
394394
ref: String = "",
395395
joinRef: String? = null
396396
) {
397-
this.trigger(Message(ref, topic, event, payload, joinRef))
397+
this.trigger(Message(joinRef, ref, topic, event, payload))
398398
}
399399

400400
internal fun trigger(message: Message) {

src/main/kotlin/org/phoenixframework/Defaults.kt

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ package org.phoenixframework
2525
import com.google.gson.FieldNamingPolicy
2626
import com.google.gson.Gson
2727
import com.google.gson.GsonBuilder
28+
import com.google.gson.reflect.TypeToken
2829
import okhttp3.HttpUrl
2930
import java.net.URL
3031

@@ -36,6 +37,9 @@ object Defaults {
3637
/** Default heartbeat interval of 30s */
3738
const val HEARTBEAT: Long = 30_000
3839

40+
/** Default JSON Serializer Version set to 2.0.0 */
41+
const val VSN: String = "2.0.0"
42+
3943
/** Default reconnect algorithm for the socket */
4044
val reconnectSteppedBackOff: (Int) -> Long = { tries ->
4145
if (tries > 9) 5_000 else listOf(
@@ -59,8 +63,21 @@ object Defaults {
5963
* Default JSON decoder, backed by GSON, that takes JSON and converts it
6064
* into a Message object.
6165
*/
66+
@Suppress("UNCHECKED_CAST")
6267
val decode: DecodeClosure = { rawMessage ->
63-
gson.fromJson(rawMessage, Message::class.java)
68+
val anyType = object : TypeToken<List<Any>>() {}.type
69+
val result = gson.fromJson<List<Any>>(rawMessage, anyType)
70+
71+
72+
// vsn=2.0.0 message structure
73+
// [join_ref, ref, topic, event, payload]
74+
Message(
75+
joinRef = result[0] as? String?,
76+
ref = result[1] as? String ?: "",
77+
topic = result[2] as? String ?: "",
78+
event = result[3] as? String ?: "",
79+
rawPayload = result[4] as? Payload ?: mapOf()
80+
)
6481
}
6582

6683
/**
@@ -81,7 +98,8 @@ object Defaults {
8198
*/
8299
internal fun buildEndpointUrl(
83100
endpoint: String,
84-
paramsClosure: PayloadClosure
101+
paramsClosure: PayloadClosure,
102+
vsn: String
85103
): URL {
86104
var mutableUrl = endpoint
87105
// Silently replace web socket URLs with HTTP URLs.
@@ -91,19 +109,20 @@ object Defaults {
91109
mutableUrl = "https:" + endpoint.substring(4)
92110
}
93111

94-
// If there are query params, append them now
95-
var httpUrl =
96-
HttpUrl.parse(mutableUrl) ?: throw IllegalArgumentException("invalid url: $endpoint")
112+
// Add the VSN query parameter
113+
var httpUrl = HttpUrl.parse(mutableUrl)
114+
?: throw IllegalArgumentException("invalid url: $endpoint")
115+
val httpBuilder = httpUrl.newBuilder()
116+
httpBuilder.addQueryParameter("vsn", vsn)
117+
118+
// Append any additional query params
97119
paramsClosure.invoke()?.let {
98-
val httpBuilder = httpUrl.newBuilder()
99120
it.forEach { (key, value) ->
100121
httpBuilder.addQueryParameter(key, value.toString())
101122
}
102-
103-
httpUrl = httpBuilder.build()
104123
}
105124

106-
// Store the URL that will be used to establish a connection
107-
return httpUrl.url()
125+
// Return the [URL] that will be used to establish a connection
126+
return httpBuilder.build().url()
108127
}
109128
}

src/main/kotlin/org/phoenixframework/Message.kt

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -22,29 +22,23 @@
2222

2323
package org.phoenixframework
2424

25-
import com.google.gson.annotations.SerializedName
2625

27-
class Message(
26+
data class Message(
27+
/** The ref sent during a join event. Empty if not present. */
28+
val joinRef: String? = null,
29+
2830
/** The unique string ref. Empty if not present */
29-
@SerializedName("ref")
3031
val ref: String = "",
3132

3233
/** The message topic */
33-
@SerializedName("topic")
3434
val topic: String = "",
3535

3636
/** The message event name, for example "phx_join" or any other custom name */
37-
@SerializedName("event")
3837
val event: String = "",
3938

4039
/** The raw payload of the message. It is recommended that you use `payload` instead. */
41-
@SerializedName("payload")
42-
val rawPayload: Payload = HashMap(),
43-
44-
/** The ref sent during a join event. Empty if not present. */
45-
@SerializedName("join_ref")
46-
val joinRef: String? = null) {
47-
40+
internal val rawPayload: Payload = HashMap()
41+
) {
4842

4943
/** The payload of the message */
5044
@Suppress("UNCHECKED_CAST")

src/main/kotlin/org/phoenixframework/Presence.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ class Presence(channel: Channel, opts: Options = Options.defaults) {
126126
if (stateEvent != null && diffEvent != null) {
127127

128128
this.channel.on(stateEvent) { message ->
129-
val newState = message.payload.toMutableMap() as PresenceState
129+
val newState = message.rawPayload.toMutableMap() as PresenceState
130130

131131
this.joinRef = this.channel.joinRef
132132
this.state =
@@ -142,7 +142,7 @@ class Presence(channel: Channel, opts: Options = Options.defaults) {
142142
}
143143

144144
this.channel.on(diffEvent) { message ->
145-
val diff = message.payload.toMutableMap() as PresenceDiff
145+
val diff = message.rawPayload.toMutableMap() as PresenceDiff
146146
if (isPendingSyncState) {
147147
this.pendingDiffs.add(diff)
148148
} else {

src/main/kotlin/org/phoenixframework/Socket.kt

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,6 @@
2222

2323
package org.phoenixframework
2424

25-
import com.google.gson.Gson
26-
import okhttp3.HttpUrl
2725
import okhttp3.OkHttpClient
2826
import okhttp3.Response
2927
import java.net.URL
@@ -105,7 +103,7 @@ const val WS_CLOSE_ABNORMAL = 1006
105103
typealias PayloadClosure = () -> Payload?
106104

107105
/** A closure that will encode a Map<String, Any> into a JSON String */
108-
typealias EncodeClosure = (Map<String, Any>) -> String
106+
typealias EncodeClosure = (Any) -> String
109107

110108
/** A closure that will decode a JSON String into a [Message] */
111109
typealias DecodeClosure = (String) -> Message
@@ -125,13 +123,15 @@ typealias DecodeClosure = (String) -> Message
125123
* ```
126124
* @param url Url to connect to such as https://example.com/socket
127125
* @param paramsClosure Closure which allows to change parameters sent during connection.
126+
* @param vsn JSON Serializer version to use. Defaults to 2.0.0
128127
* @param encode Optional. Provide a custom JSON encoding implementation
129128
* @param decode Optional. Provide a custom JSON decoding implementation
130129
* @param client Default OkHttpClient to connect with. You can provide your own if needed.
131130
*/
132131
class Socket(
133132
url: String,
134133
val paramsClosure: PayloadClosure,
134+
val vsn: String = Defaults.VSN,
135135
private val encode: EncodeClosure = Defaults.encode,
136136
private val decode: DecodeClosure = Defaults.decode,
137137
private val client: OkHttpClient = OkHttpClient.Builder().build()
@@ -235,17 +235,19 @@ class Socket(
235235
*
236236
* @param url Url to connect to such as https://example.com/socket
237237
* @param params Constant parameters to send when connecting. Defaults to null
238+
* @param vsn JSON Serializer version to use. Defaults to 2.0.0
238239
* @param encode Optional. Provide a custom JSON encoding implementation
239240
* @param decode Optional. Provide a custom JSON decoding implementation
240241
* @param client Default OkHttpClient to connect with. You can provide your own if needed.
241242
*/
242243
constructor(
243244
url: String,
244245
params: Payload? = null,
246+
vsn: String = Defaults.VSN,
245247
encode: EncodeClosure = Defaults.encode,
246248
decode: DecodeClosure = Defaults.decode,
247249
client: OkHttpClient = OkHttpClient.Builder().build()
248-
) : this(url, { params }, encode, decode, client)
250+
) : this(url, { params }, vsn, encode, decode, client)
249251

250252
init {
251253
var mutableUrl = url
@@ -266,7 +268,7 @@ class Socket(
266268

267269
// Store the URL that will be used to establish a connection. Could potentially be
268270
// different at the time connect() is called based on a changing params closure.
269-
this.endpointUrl = Defaults.buildEndpointUrl(this.endpoint, this.paramsClosure)
271+
this.endpointUrl = Defaults.buildEndpointUrl(this.endpoint, this.paramsClosure, this.vsn)
270272

271273
// Create reconnect timer
272274
this.reconnectTimer = TimeoutTimer(
@@ -305,7 +307,7 @@ class Socket(
305307

306308
// Build the new endpointUrl with the params closure. The payload returned
307309
// from the closure could be different such as a changing authToken.
308-
this.endpointUrl = Defaults.buildEndpointUrl(this.endpoint, this.paramsClosure)
310+
this.endpointUrl = Defaults.buildEndpointUrl(this.endpoint, this.paramsClosure, this.vsn)
309311

310312
// Now create the connection transport and attempt to connect
311313
this.connection = this.transport(endpointUrl)
@@ -390,14 +392,7 @@ class Socket(
390392
) {
391393

392394
val callback: (() -> Unit) = {
393-
val body = mutableMapOf<String, Any>()
394-
body["topic"] = topic
395-
body["event"] = event
396-
body["payload"] = payload
397-
398-
ref?.let { body["ref"] = it }
399-
joinRef?.let { body["join_ref"] = it }
400-
395+
val body = listOf(joinRef, ref, topic, event, payload)
401396
val data = this.encode(body)
402397
connection?.let { transport ->
403398
this.logItems("Push: Sending $data")

src/test/kotlin/org/phoenixframework/DefaultsTest.kt

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,26 @@ internal class DefaultsTest {
4242
assertThat(reconnect(4)).isEqualTo(10_000)
4343
assertThat(reconnect(5)).isEqualTo(10_000)
4444
}
45+
46+
47+
@Test
48+
internal fun `decoder converts json array into message`() {
49+
val v2Json = """
50+
[null,null,"room:lobby","shout",{"message":"Hi","name":"Tester"}]
51+
""".trimIndent()
52+
53+
val message = Defaults.decode(v2Json)
54+
assertThat(message.joinRef).isNull()
55+
assertThat(message.ref).isEqualTo("")
56+
assertThat(message.topic).isEqualTo("room:lobby")
57+
assertThat(message.event).isEqualTo("shout")
58+
assertThat(message.payload).isEqualTo(mapOf("message" to "Hi", "name" to "Tester"))
59+
}
60+
61+
@Test
62+
internal fun `encode converts message into json`() {
63+
val body = listOf(null, null, "topic", "event", mapOf("one" to "two"))
64+
assertThat(Defaults.encode(body))
65+
.isEqualTo("[null,null,\"topic\",\"event\",{\"one\":\"two\"}]")
66+
}
4567
}

src/test/kotlin/org/phoenixframework/MessageTest.kt

Lines changed: 2 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,7 @@ class MessageTest {
1414
@Test
1515
internal fun `jsonParsing parses normal message`() {
1616
val json = """
17-
{
18-
"event": "update",
19-
"payload": {
20-
"user": "James S.",
21-
"message": "This is a test"
22-
},
23-
"ref": "6",
24-
"topic": "my-topic"
25-
}
17+
[null, "6", "my-topic", "update", {"user": "James S.", "message": "This is a test"}]
2618
""".trimIndent()
2719

2820
val message = Defaults.decode.invoke(json)
@@ -38,18 +30,7 @@ class MessageTest {
3830
@Test
3931
internal fun `jsonParsing parses a reply`() {
4032
val json = """
41-
{
42-
"event": "phx_reply",
43-
"payload": {
44-
"response": {
45-
"user": "James S.",
46-
"message": "This is a test"
47-
},
48-
"status": "ok"
49-
},
50-
"ref": "6",
51-
"topic": "my-topic"
52-
}
33+
[null, "6", "my-topic", "phx_reply", {"response": {"user": "James S.","message": "This is a test"},"status": "ok"}]
5334
""".trimIndent()
5435

5536
val message = Defaults.decode.invoke(json)

0 commit comments

Comments
 (0)