Skip to content

Commit eb12bc2

Browse files
authored
Merge pull request #93 from dsrees/feature/include-raw-json-in-message
Include the payload as a json string in message
2 parents 0aec997 + fdebc1c commit eb12bc2

File tree

3 files changed

+93
-9
lines changed

3 files changed

+93
-9
lines changed

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

+35-7
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ 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.JsonObject
29+
import com.google.gson.JsonParser
2830
import com.google.gson.reflect.TypeToken
2931
import okhttp3.HttpUrl
3032
import java.net.URL
@@ -65,18 +67,44 @@ object Defaults {
6567
*/
6668
@Suppress("UNCHECKED_CAST")
6769
val decode: DecodeClosure = { rawMessage ->
68-
val anyType = object : TypeToken<List<Any>>() {}.type
69-
val result = gson.fromJson<List<Any>>(rawMessage, anyType)
7070

71+
var message = rawMessage
72+
message = message.removeRange(0, 1) // remove '['
73+
74+
val joinRef = message.takeWhile { it != ',' } // take join ref, 'null' or '5'
75+
message = message.removeRange(0, joinRef.length) // remove join ref
76+
message = message.removeRange(0, 1) // remove ','
77+
78+
val ref = message.takeWhile { it != ',' } // take ref, 'null' or '5'
79+
message = message.removeRange(0, ref.length) // remove ref
80+
message = message.removeRange(0, 2) // remove ',"'
81+
82+
val topic = message.takeWhile { it != '"' }
83+
message = message.removeRange(0, topic.length)
84+
message = message.removeRange(0, 3) // remove '","'
85+
86+
val event = message.takeWhile { it != '"' }
87+
message = message.removeRange(0, event.length)
88+
message = message.removeRange(0, 2) // remove '",'
89+
90+
val remaining = message.removeRange(message.length - 1, message.length)
91+
92+
val jsonObj = gson.fromJson(remaining, JsonObject::class.java)
93+
val response = jsonObj.get("response")
94+
val payload = response?.let { gson.toJson(response) } ?: remaining
95+
96+
val anyType = object : TypeToken<Map<String, Any>>() {}.type
97+
val result = gson.fromJson<Map<String, Any>>(remaining, anyType)
7198

7299
// vsn=2.0.0 message structure
73100
// [join_ref, ref, topic, event, payload]
74101
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()
102+
joinRef = joinRef.toIntOrNull()?.toString(),
103+
ref = ref.toIntOrNull()?.toString() ?: "",
104+
topic = topic,
105+
event = event,
106+
rawPayload = result,
107+
payloadJson = payload
80108
)
81109
}
82110

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

+4-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,10 @@ data class Message(
3737
val event: String = "",
3838

3939
/** The raw payload of the message. It is recommended that you use `payload` instead. */
40-
internal val rawPayload: Payload = HashMap()
40+
internal val rawPayload: Payload = HashMap(),
41+
42+
/** The payload, as a json string */
43+
val payloadJson: String = ""
4144
) {
4245

4346
/** The payload of the message */

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

+54-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@ internal class DefaultsTest {
4343
assertThat(reconnect(5)).isEqualTo(10_000)
4444
}
4545

46-
4746
@Test
4847
internal fun `decoder converts json array into message`() {
4948
val v2Json = """
@@ -58,6 +57,60 @@ internal class DefaultsTest {
5857
assertThat(message.payload).isEqualTo(mapOf("message" to "Hi", "name" to "Tester"))
5958
}
6059

60+
@Test
61+
internal fun `decoder provides raw json payload`() {
62+
val v2Json = """
63+
[1,2,"room:lobby","shout",{"message":"Hi","name":"Tester","count":15,"ratio":0.2}]
64+
""".trimIndent()
65+
66+
val message = Defaults.decode(v2Json)
67+
assertThat(message.joinRef).isEqualTo("1")
68+
assertThat(message.ref).isEqualTo("2")
69+
assertThat(message.topic).isEqualTo("room:lobby")
70+
assertThat(message.event).isEqualTo("shout")
71+
assertThat(message.payloadJson).isEqualTo("{\"message\":\"Hi\",\"name\":\"Tester\",\"count\":15,\"ratio\":0.2}")
72+
assertThat(message.payload).isEqualTo(mapOf(
73+
"message" to "Hi",
74+
"name" to "Tester",
75+
"count" to 15.0, // Note that this is a bug and should eventually be removed
76+
"ratio" to 0.2
77+
))
78+
}
79+
80+
@Test
81+
internal fun `decoder decodes a status`() {
82+
val v2Json = """
83+
[1,2,"room:lobby","phx_reply",{"response":{"message":"Hi","name":"Tester","count":15,"ratio":0.2},"status":"ok"}]
84+
""".trimIndent()
85+
86+
val message = Defaults.decode(v2Json)
87+
assertThat(message.joinRef).isEqualTo("1")
88+
assertThat(message.ref).isEqualTo("2")
89+
assertThat(message.topic).isEqualTo("room:lobby")
90+
assertThat(message.event).isEqualTo("phx_reply")
91+
assertThat(message.payloadJson).isEqualTo("{\"message\":\"Hi\",\"name\":\"Tester\",\"count\":15,\"ratio\":0.2}")
92+
assertThat(message.payload).isEqualTo(mapOf(
93+
"message" to "Hi",
94+
"name" to "Tester",
95+
"count" to 15.0, // Note that this is a bug and should eventually be removed
96+
"ratio" to 0.2
97+
))
98+
}
99+
100+
@Test
101+
internal fun `decoder decodes a non-json payload`() {
102+
val v2Json = """
103+
[1,2,"room:lobby","phx_reply",{"response":"hello","status":"ok"}]
104+
""".trimIndent()
105+
106+
val message = Defaults.decode(v2Json)
107+
assertThat(message.payloadJson).isEqualTo("\"hello\"")
108+
assertThat(message.payload).isEqualTo(mapOf(
109+
"response" to "hello",
110+
"status" to "ok"
111+
))
112+
}
113+
61114
@Test
62115
internal fun `encode converts message into json`() {
63116
val body = listOf(null, null, "topic", "event", mapOf("one" to "two"))

0 commit comments

Comments
 (0)