Hi! I Try to parse this class from json [1] Server...
# serialization
i
Hi! I Try to parse this class from json [1] ServerErrors is enum that should be deserialized well [2] I receive body [3] and try to parse it and get error [4] I can read and see what is wrote in, but i had this flag enabled in my json plugin in client [5] What can i miss?
🧵 1
[1]
Copy code
@Serializable
data class Simple(val errorCode: ServerErrors)
[2]
Copy code
@Serializable
enum class ServerErrors {
    @SerialName("TMP_PASS_ACCESS_FORBIDDEN")
    TmpPassAccessForbidden,
...
}
[3]
Copy code
{
  "errorCode": "CAPTCHA_REQUIRED",
  "captchaId": "g378c6b58736c5u38d6u3huh",
  "captchaUrl": "<https://miro.medium.com/max/2400/1*uq_w8ytWwx5GjmFzgTUwqw.gif>"
}
[4]
Copy code
Can not parse Simple from {
      "errorCode" : "CAPTCHA_REQUIRED",
      "captchaId": "g378c6b58736c5u38d6u3huh",
      "captchaUrl": "<https://miro.medium.com/max/2400/1*uq_w8ytWwx5GjmFzgTUwqw.gif>"
    }
    kotlinx.serialization.json.internal.JsonDecodingException: Unexpected JSON token at offset 41: Encountered an unknown key 'captchaId'.
    Use 'ignoreUnknownKeys = true' in 'Json {}' builder to ignore unknown keys.
    JSON input: {
      "errorCode" : "CAPTCHA_REQUIRED",
      "captchaId": "g378c6b58736c5u38d6u3huh",
      "captchaUrl": "<https://miro.medium.com/max/2400/1*uq_w8ytWwx5GjmFzgTUwqw.gif>"
    }
[5]
Copy code
@OptIn(ExperimentalSerializationApi::class)
    val client: HttpClient by lazy {
        HttpConfig.httpClient(providedProxy = proxy) {
            Json {
                serializer = KotlinxSerializer(
                    kotlinx.serialization.json.Json {
                        encodeDefaults = true
                        ignoreUnknownKeys = true
                        useAlternativeNames = false
                        isLenient = true
                        explicitNulls = false
                    }
                )
            }
n
your json config should be
Copy code
Json {
    encodeDefaults = true
    ignoreUnknownKeys = true
    useAlternativeNames = false
    isLenient = true
    explicitNulls = false
}
or such, or is that a different type ?
i
as you see. I posted it in [5]
n
when dealing with http responses.. try to decode it by hand using a Json instance..
i
Why?
n
because it looks like whatever code is running might not use the Json configuration you passed in
the serializables and json config look sane
in kto-client this should look like so for example
Copy code
val client = HttpClient(httpEngine) {
    install(ContentNegotiation) {
        json(
            Json {
                encodeDefaults = true
                ignoreUnknownKeys = true
                useAlternativeNames = false
                isLenient = true
                explicitNulls = false
            }
        )
    }
}
not sure what that
HttpConfig.httpClient()
call of yours is from
i
How about this?
HttpConfig.httpClient() is just multiplatform initialization
On android, for example
n
@Deprecated("Please use ContentNegotiation plugin and its converters")
at least that what my IDE got to say about that.. seems like the website and the deprecation notices are not in sync, old ktor version ?
i
Copy code
1.6.0
n
oh right,, i have been using ktor 2.0.0, gotta dig out a project where i do this in kotlin 1.6.0 i guess
i
Strange thing is that configuration (that i post) worked, i develop app with it almost a year. I cant believe that i never met
unknown keys
in json before (but it is possible)
n
either way.. i would try to just receive responses as
String
and dealing with them by hand, see if it also breaks, then its the classes or json config if not.. maybe something in ktor is improperly configured.. i barely used that
JsonFeature
before 2.0.0 myself.. it just seemed too flaky
i
looks like duct tape
Understood
Sorry, i mislead you to wrong way
Ktor works good, but in the point when i got error i use deserialization directly without ktor
Copy code
json.tryFromJson<Simple>(content)?.let { simpleError ->
    when (simpleError.errorCode) {
        ServerErrors.IpTemporaryBlocked, ServerErrors.UserTemporaryBlocked ->
            json.fromJson<TimeBlock>(content)
        ServerErrors.CaptchaRequired -> json.fromJson<CaptchaRequired>(content)
        ServerErrors.CodeTimeout -> json.fromJson<CodeTimeout>(content)
        ServerErrors.InvalidOtp -> json.fromJson<InvalidOtp>(content)
        else -> simpleError
    }
} ?: Unknown(throwable)