Reputation: 21
I'm trying to parse newline delimited json using retrofit and moshi. This is my GET function:
suspend fun getDeviceValuesNew(@Path("application-id") applicationId: String, @Path("device-id") deviceId: String)
: Response<List<ValueApiResponse>>
When I try to run it, I get this error:
com.squareup.moshi.JsonDataException: Expected BEGIN_ARRAY but was BEGIN_OBJECT at path $
The HTTP call returns json like this:
{
"result": {
"end_device_ids": {
"device_id": "esp32",
"application_ids": {}
},
"received_at": "2021-03-31T11:33:42.757281753Z",
"uplink_message": {
"decoded_payload": {
"brightness": 0
},
"settings": {
"data_rate": {}
},
"received_at": "2021-03-31T11:33:42.547285090Z"
}
}
}
{
"result": {
"end_device_ids": {
"device_id": "esp32",
"application_ids": {}
},
"received_at": "2021-03-31T11:18:17.745921472Z",
"uplink_message": {
"decoded_payload": {
"brightness": 0
},
"settings": {
"data_rate": {}
},
"received_at": "2021-03-31T11:18:17.538276218Z"
}
}
}
EDIT #1: As you can see in my answer below, I managed to get a valid JSON response from the API, but still I'm struggling to parse these JSON objects to a list of Kotlin objects. How do I get Moshi to handle these newline delimited JSON objects as a list? I think the problem is that Moshi requires the objects to be wrapped inside an array to be recognised as a list. How do I do that?
This is my data class used for parsing:
@JsonClass(generateAdapter = true)
data class ValueDto(
@Json(name = "result")
val result: Result
) {
@JsonClass(generateAdapter = true)
data class Result(
@Json(name = "end_device_ids")
val endDeviceIds: EndDeviceIds,
@Json(name = "received_at")
val receivedAt: String,
@Json(name = "uplink_message")
val uplinkMessage: UplinkMessage
) {
@JsonClass(generateAdapter = true)
data class EndDeviceIds(
@Json(name = "application_ids")
val applicationIds: ApplicationIds,
@Json(name = "device_id")
val deviceId: String
) {
@JsonClass(generateAdapter = true)
class ApplicationIds(
)
}
@JsonClass(generateAdapter = true)
data class UplinkMessage(
@Json(name = "decoded_payload")
val decodedPayload: DecodedPayload,
@Json(name = "received_at")
val receivedAt: String,
@Json(name = "settings")
val settings: Settings
) {
@JsonClass(generateAdapter = true)
data class DecodedPayload(
@Json(name = "brightness")
val brightness: Int
)
@JsonClass(generateAdapter = true)
data class Settings(
@Json(name = "data_rate")
val dataRate: DataRate
) {
@JsonClass(generateAdapter = true)
class DataRate(
)
}
}
}
}
Upvotes: 0
Views: 637
Reputation: 21
@tyczj was right, this is not valid ndjson, as in ndjson newline characters only appear after each seperate json text. The solution was to send Accept: text/event-stream
with the HTTP request and now I'm getting a valid ndjson response like this:
{"result":{"end_device_ids":{"device_id":"esp32-bh1750","application_ids":{}},"received_at":"2021-04-24T10:19:04.021238048Z","uplink_message":{"decoded_payload":{"brightness":0},"settings":{"data_rate":{}},"received_at":"2021-04-24T10:19:03.809173924Z"}}}
{"result":{"end_device_ids":{"device_id":"esp32-bh1750","application_ids":{}},"received_at":"2021-04-24T10:25:22.260712161Z","uplink_message":{"decoded_payload":{"brightness":119},"settings":{"data_rate":{}},"received_at":"2021-04-24T10:25:22.046086937Z"}}}
{"result":{"end_device_ids":{"device_id":"esp32-bh1750","application_ids":{}},"received_at":"2021-04-24T10:18:58.438947740Z","uplink_message":{"decoded_payload":{"brightness":0},"settings":{"data_rate":{}},"received_at":"2021-04-24T10:18:58.228671174Z"}}}
{"result":{"end_device_ids":{"device_id":"esp32-bh1750","application_ids":{}},"received_at":"2021-04-24T10:21:10.102303310Z","uplink_message":{"decoded_payload":{"brightness":106},"settings":{"data_rate":{}},"received_at":"2021-04-24T10:21:09.893217735Z"}}}
{"result":{"end_device_ids":{"device_id":"esp32-bh1750","application_ids":{}},"received_at":"2021-04-24T10:23:16.177064041Z","uplink_message":{"decoded_payload":{"brightness":108},"settings":{"data_rate":{}},"received_at":"2021-04-24T10:23:15.967959055Z"}}}
{"result":{"end_device_ids":{"device_id":"esp32-bh1750","application_ids":{}},"received_at":"2021-04-24T10:27:28.334312076Z","uplink_message":{"decoded_payload":{"brightness":117},"settings":{"data_rate":{}},"received_at":"2021-04-24T10:27:28.126104222Z"}}}
{"result":{"end_device_ids":{"device_id":"esp32-bh1750","application_ids":{}},"received_at":"2021-04-24T10:29:34.400253264Z","uplink_message":{"decoded_payload":{"brightness":99},"settings":{"data_rate":{}},"received_at":"2021-04-24T10:29:34.190980301Z"}}}
{"result":{"end_device_ids":{"device_id":"esp32-bh1750","application_ids":{}},"received_at":"2021-04-24T10:31:40.481766225Z","uplink_message":{"decoded_payload":{"brightness":118},"settings":{"data_rate":{}},"received_at":"2021-04-24T10:31:40.270452429Z"}}}
{"result":{"end_device_ids":{"device_id":"esp32-bh1750","application_ids":{}},"received_at":"2021-04-24T10:33:46.567235913Z","uplink_message":{"decoded_payload":{"brightness":114},"settings":{"data_rate":{}},"received_at":"2021-04-24T10:33:46.357373037Z"}}}
{"result":{"end_device_ids":{"device_id":"esp32-bh1750","application_ids":{}},"received_at":"2021-04-24T10:35:52.737386496Z","uplink_message":{"decoded_payload":{"brightness":121},"settings":{"data_rate":{}},"received_at":"2021-04-24T10:35:52.426583804Z"}}}
I've added the Header via retrofit annotation:
@Headers("Accept: text/event-stream ")
Upvotes: 1