Description:
Nested JsonObject values within track event properties are sent to Segment servers as empty objects {}, while the equivalent structure works correctly with the Swift SDK (analytics-swift).
Environment:
- analytics-kotlin version: 1.24.1 (also reproduced on 1.22.0)
- Android API: 35
- Kotlin: 2.0.21
- kotlinx.serialization: (bundled with SDK)
- Device: Pixel emulator (sdk_gphone64_arm64), Android 15
Steps to Reproduce:
val props = buildJsonObject {
putJsonObject("selected_values") {
putJsonArray("key") {
add(JsonPrimitive("value_1"))
add(JsonPrimitive("value_2"))
}
}
put("skipped", false)
}
// Log confirms correct structure:
// {"selected_values":{"key":["value_1","value_2"]},"skipped":false}
Log.i("Debug", "payload: $props")
analytics.track("Tracking Event", props)
Expected Result:
Segment receives:
{
"properties": {
"selected_values": {
"key": ["value_1", "value_2"]
},
"skipped": false
}
}
Actual Result:
Segment raw data shows:
{
"properties": {
"selected_values": {},
"skipped": false
},
"context": {
"protocols": {
"omitted": ["selected_values.key"]
}
}
}
The nested object arrives empty and the nested field appears in protocols.omitted.
Additional context:
- The JsonObject is correct in memory — logging .toString() before passing to analytics.track() shows the full nested structure
- We tried multiple approaches: buildJsonObject with putJsonObject/putJsonArray, JsonObject(map) constructor, and re-parsing via Json.parseToJsonElement() — all produce the same empty result on the server
- The identical event structure sent from analytics-swift (iOS) works correctly — the same Segment source and tracking plan receives the nested object with all data intact
- Flat properties (strings, booleans, numbers) work fine — only nested objects are affected
Description:
Nested JsonObject values within track event properties are sent to Segment servers as empty objects {}, while the equivalent structure works correctly with the Swift SDK (analytics-swift).
Environment:
Steps to Reproduce:
Expected Result:
Segment receives:
Actual Result:
Segment raw data shows:
The nested object arrives empty and the nested field appears in protocols.omitted.
Additional context: