0

got a bit of a problem with creating a data class. First post, and a bit of a noob - be gentle :)

I'm trying to create a Kotlin data class to handle some responses from an API we use; the response of which looks a bit like this:

"data": {
        "devices": {
            "600": [
                {
                    "device_id": "[deviceId]", ...

What I'm having trouble with is the "600" bit - I can't find a way to create the data class with this as a parameter. Each time I declare the var/val - it's throwing an error, but doesn't provide any helpful options in the IDE. All the rest are strings, so "devices" becomes "val devices: String" and so on. But in this case the val is an Int, and I don't know how to declare this in the data class.

I want to have the API response re-worked to something more easily defined, but that'll take time. Can anyone tell me how I can pass the Int as the parameter?

This is the data class:

data class SimRetrieveDevicesResponse(
    val data: Devices,
    val error: String? = null,
)

data class Devices(
   
    val 600: List<DeviceInfo>? = null
   )

data class DeviceInfo(
    val device_id: String,
    val device_type: String,
    val network_id: String,
    val send_period_sec: Int,
    val loss_in_thousand: Int,
    val tti_application_id: String,
    val cmt_tenant_id: String,
)

Sorry I've called anything the wrong name...

11
  • Post the exact error message and the code that causes the error. Commented Mar 10, 2022 at 12:17
  • Updated the description Commented Mar 10, 2022 at 12:20
  • 2
    without knowing the full json object, devices might just be a Map<Int, List<Something>>, then it is not a parameter, just a key in a map. Commented Mar 10, 2022 at 12:21
  • 1
    Which library/classes are you using to deserialize the JSON into classes? You can use normally invalid property names by surrounding them with backticks, like `val ``600```. I bet the Kotlin Deserialization library can handle it this way, but a Java library like JSON might not be equipped to, and would need you to use a different name and use an annotation. Commented Mar 10, 2022 at 12:31
  • How would that look? As said above - bit of a noob. I've updated the description again with the elements of the list that would be returned. Commented Mar 10, 2022 at 12:32

2 Answers 2

0

Backtick-ing the val has fixed the error, and helped tremendously.

Sign up to request clarification or add additional context in comments.

1 Comment

Depending on the library you're using to deserialise the JSON, you can probably name the parameter whatever you want in your class, and annotate it with a serialised name (i.e. "600"). It just might make it easier than having to use backticks everywhere you deal with it (and if 600 isn't a very descriptive name and you're just putting up with it, you can give it a more useful one). Whatever works for you, just letting you know you have options!
0

As stated in the comments, the mapping is more than likely for a map, so having a property called "600", back-ticked or not, is incorrect. As soon as you have another value like "700", you'd have to change your code.

Here's a working solution, based on the assumption from your JSON snippet that devices is a map of a list of device information:

import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import io.kotest.assertions.withClue
import io.kotest.matchers.shouldBe
import io.kotest.matchers.shouldNotBe
import org.junit.jupiter.api.Test

data class SimRetrieveDevicesResponse(
    val data: Devices,
    val error: String? = null,
)

data class Devices(val devices: Map<String, List<DeviceInfo>>)
data class DeviceInfo(
    val device_id: String,
    val device_type: String,
    val network_id: String,
    val send_period_sec: Int,
    val loss_in_thousand: Int,
    val tti_application_id: String,
    val cmt_tenant_id: String,
)

class StackOverFlowTest {
    @Test
    fun test() {

        val data = """
       {
         "data": {
           "devices": {
             "600": [
               {
                 "device_id": "device_id",
                 "device_type": "device_type",
                 "network_id": "network_id",
                 "send_period_sec": 2,
                 "loss_in_thousand": 3,
                 "tti_application_id": "tti_application_id",
                 "cmt_tenant_id": "cmt_tenant_id"
                 
               }
             ]
           }
         }
       }
      """.trimIndent()

        val mapper = jacksonObjectMapper()

        val response = mapper.readValue(data, SimRetrieveDevicesResponse::class.java)

        val device = response.data.devices["600"]
        withClue("Device should be present") {
            device.shouldNotBe(null)
        }
        device!!.first().device_id shouldBe "device_id"
    }
}

The assertions here use kotest, which you can add via this in your build.gradle.kts

testImplementation("io.kotest:kotest-assertions-core:$kotestVersion")

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.