Burf2000
Burf2000

Reputation: 5193

Parsing JSON in Kotlin Multiplatform : io.ktor.serialization.JsonConvertException: Illegal input

I am taking my first look at Kotlin Multiplatform and am following the guide here

https://kotlinlang.org/docs/multiplatform-mobile-upgrade-app.html

I have my class

@Serializable
data class RocketLaunch (
    @SerialName("flight_number")
    val flightNumber: Int,
    @SerialName("name")
    val missionName: String,
    @SerialName("date_utc")
    val launchDateUTC: String,
    @SerialName("success")
    val launchSuccess: Boolean?,
)

I instantiate a HTTPClient and call the SpaceX URL as detailed in the guide

private val httpClient = HttpClient {
        install(ContentNegotiation) {
            json(Json {
                prettyPrint = true
                isLenient = true
                ignoreUnknownKeys = true
            })
        }
    }

    @Throws(Exception::class)
    suspend fun greet(): String {
        val rockets: List<RocketLaunch> = httpClient.get("https://api.spacexdata.com/v4/launches").body()
        val lastSuccessLaunch = rockets.first() //{ it.launchSuccess == true }
        return "Guess what it is! > ${platform.name.reversed()}!"
                "\nThe last successful launch was ${lastSuccessLaunch.title} 🚀"
    }

And when I run it and catch the exception I get

kotlinx.serialization.json.internal.JsonDecodingException: Expected class kotlinx.serialization.json.JsonObject (Kotlin reflection is not available) as the serialized body of kotlinx.serialization.Polymorphic, but had class kotlinx.serialization.json.JsonArray (Kotlin reflection is not available)

I have double checked and I am following the guide properly, and the feed works

Plugin

kotlin("plugin.serialization") version "1.8.10"

Dependancies

implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4")

implementation("io.ktor:ktor-client-core:$ktorVersion")

implementation("io.ktor:ktor-client-content-negotiation:$ktorVersion")

implementation("io.ktor:ktor-serialization-kotlinx-json:$ktorVersion")

Upvotes: 9

Views: 10546

Answers (4)

Shubham Kumar Gupta
Shubham Kumar Gupta

Reputation: 1147

in my case for similar problem i tried almost everything

isLinient = true

object KTorClient{
    val client = HttpClient {
        install(ContentNegotiation) {
            json(json = Json{
                isLenient = true
                ignoreUnknownKeys = true
            })
        }
    }
}

tried adding serialize name annotation for the class and all internal data classes

@Serializable
data class SysDTO(
    @SerialName("country")
    val country: String,
    @SerialName("sunrise")
    val sunrise: Int,
    @SerialName("sunset")
    val sunset: Int
)

I tried adding top level gradle

plugins {
    alias(libs.plugins.kotlinx.serialization).apply(false) //
    id("com.google.devtools.ksp") version "2.1.10-1.0.30"
}

kotlinx-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlinxSerialization" }

in project level

plugins {
    alias(libs.plugins.kotlinMultiplatform)
    alias(libs.plugins.androidLibrary)
    id("com.google.devtools.ksp")
    id("kotlinx-serialization") // added this
}

then also it showed same error io.ktor.serialization.JsonConvertException: Illegal input

Then I read this

You have defined nullable fields like displayIndex in your serializable classes. kotlinx.serialization 

however differentiates between null and field is missing. 

Therefore you need to initialize optional fields with a value, probably null.

So you write val displayIndex: Long? = null, in that case.

See this discussion for more information: 

https://github.com/Kotlin/kotlinx.serialization/issues/1196#issuecomment-725811719

This helped me and I changed code to this

@Serializable
data class SysDTO(
    @SerialName("country")
    val country: String? = null,
    @SerialName("sunrise")
    val sunrise: Int? = null,
    @SerialName("sunset")
    val sunset: Int? = null
)

and it started working!! It may help someone!

Upvotes: 0

Foroogh Varmazyar
Foroogh Varmazyar

Reputation: 1605

if you are using version catalog

[versions]
kotlin = "1.9.21"
ktor = "2.3.7"

[libraries]
ktor-client-content-negotiation = { module = "io.ktor:ktor-client-content-negotiation", version.ref = "ktor" }
ktor-serialization-kotlinx-json = { module = "io.ktor:ktor-serialization-kotlinx-json", version.ref = "ktor" }

[plugins]
kotlinxSerialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }

Upvotes: 5

X.Liang
X.Liang

Reputation: 21

I ran into the same error, what I did was to change kotlin("plugin.serialization") version "1.8.21" to id("org.jetbrains.kotlin.plugin.serialization") version "1.8.21" in shared build.gradle.kts, and the problem was solved.

plugins {
    kotlin("multiplatform")
    id("com.android.library")
    id("org.jetbrains.kotlin.plugin.serialization") version "1.8.21"
}

Upvotes: 2

Burf2000
Burf2000

Reputation: 5193

The fix was to add

id("kotlinx-serialization") e.g.

plugins {
    kotlin("multiplatform")
    id("com.android.library")
    id("kotlinx-serialization")
}

To the shared build.gradle.kts file. I find this odd as it was added to the Project level one as shown below.

kotlin("plugin.serialization") version "1.8.10"

Upvotes: 4

Related Questions