androiddesktopkotlin-multiplatformcompose-multiplatform

Parsing JSON in kotlin multiplatform Android and Desktop


I have a JSON Object:

{
  "1": {
    "unique_id": 24332432,
    "title": "Title 1...",
    "url": "https://example.com",
    "chapter": "1",
    "publisher": "Publisher Name",
    "pub_type": "Admin",
    "logo": "A",
    "logo_bg": "#acacf9"
  },
  "3": {
    "unique_id": 15764356,
    "title": "Title 3...",
    "url": "https://example.com",
    "chapter": "1",
    "publisher": "Publisher Name",
    "pub_type": "Admin",
    "logo": "A",
    "logo_bg": "#acacf9"
  }
  "num-of-rows": 3
}

Using kotlinx.serialization, I want to convert it into kotlin readable format. As visible in the example, some numbers may be missing, and the numbers can be any number greater than 1.

To parse, I attempted with the following kotlin code:

@Serializable
data class Item(
    @SerialName("unique_id") val uniqueId: Int = 111111111,
    @SerialName("title") val title: String = "",
    @SerialName("url") val url: String = "",
    @SerialName("chapter") val chapter: String = "",
    @SerialName("publisher") val publisher: String = "",
    @SerialName("pub_type") val pubType: String = "",
    @SerialName("logo") val logo: String = "",
    @SerialName("logo_bg") val logoBg: String = "",
    @SerialName("specification") val specification: String = "",
    @SerialName("author") val author: String = "",
    @SerialName("published") val published: String = "",
    @SerialName("description") val description: String = ""
)

@Serializable
data class ItemsResponse(
    @SerialName("num-of-rows") val numOfRows: Int,
    val items: Map<String, Item>
)

fun parseJson(jsonString: String): ItemsResponse {
    try {
        val json = Json { ignoreUnknownKeys = true }
        return json.decodeFromString(jsonString)
    } catch (e: Exception) {
        println(e)
        return ItemsResponse(0, emptyMap())
    }
}

The methods also show that all the required sub-fields in the sub-JSON-Objects may not be present, and so a default value has been provided for every sub-field.

Finally, I call the function as:

val itemsResponse = parseJson(data)

itemsResponse.items.values.forEach { item ->
                    Item(
                        logo = item.logo,
                        logoColor = parseColor(item.logoBg),
                        chapter = item.chapter,
                        publisher = item.publisher,
                        title = item.title,
                        description = item.description,
                        specification = item.specification,
                        author = item.author,
                        published = item.published,
                        url = item.url
                    )
                }

Where Item() is a Composable function and data contains the JSON array retrieved from server via an API.

However, when I run this code, I get the following exception: kotlinx.serialization.MissingFieldException: Field 'items' is required for type with serial name 'screens.resources.ItemsResponse', but it was missing at path: $

I understand that it is looking for a field called item, while it is actually the numbers. How do I declare the serializable classes or manipulate the code such that every sub-array is returned in the map?


Solution

  • Anyhow, I managed to do it with Gson, as it works in compose multiplatform. Thanks for everybody's help.

    UPDATE: If anyone comes across this scenario, I used JsonReader to parse the JSON.