hey all, I'm having some trouble with dynamic deserialization on kotlin native. i've included releva...
r
hey all, I'm having some trouble with dynamic deserialization on kotlin native. i've included relevant code in the thread. would appreciate some help on this one, thank you in advance!
Copy code
private fun <ResponseType> deserializeBaseResponse(
        body: String,
        responseDeserializer: KSerializer<ResponseType>
    ): Pair<HttpStatusCode, ResponseType?> {
        val response = json.decodeFromString(BaseResponse.serializer(responseDeserializer), body)
        return Pair(response.code.toHttpStatusCode(), response.response)
    }
Here's where I'm trying to do some dynamic deserialization. I have a data type that is wrapped by
BaseResponse
. Here's the
BaseResponse
data class:
Copy code
@Serializable
data class BaseResponse<T>(
    @SerialName("code")
    val code: Int,

    @SerialName("response")
    var response: T? = null
)
crash from ios
Copy code
Uncaught Kotlin exception: kotlin.native.concurrent.InvalidMutabilityException: mutation attempt of frozen kotlin.collections.HashMap@322768
    at 0   Shared                              0x000000010aaba050 ThrowInvalidMutabilityException + 208
    at 1   Shared                              0x000000010aaaf647 <kfun:kotlin.collections.HashMap#addKey(1:0){}kotlin.Int> + 1447
    at 2   Shared                              0x000000010aaabe0a <kfun:kotlin.collections.HashMap#put(1:0;1:1){}1:1>? + 106
    at 3   Shared                              0x000000010ab85fba <kfun:kotlinx.serialization.json.internal.DescriptorSchemaCache#getOrPut(kotlinx.serialization.descriptors.SerialDescriptor;kotlinx.serialization.json.internal.DescriptorSchemaCache.Key><0:0>;kotlin.Function0<0:0>){0§<kotlin.Any>}0:0 + 474
    at 4   Shared                              0x000000010ab879d5 <kfun:kotlinx.serialization.json.internal.StreamingJsonDecoder#decodeElementIndex(kotlinx.serialization.descriptors.SerialDescriptor){}kotlin.Int> + 2597
    at 5   Shared                              0x000000010abe2f7a <kfun:app.shred.kmp.shared.network.BaseResponse>.$serializer#deserialize(kotlinx.serialization.encoding.Decoder){}app.shred.kmp.shared.network.BaseResponse<2:0> + 538
    at 6   Shared                              0x000000010ab8429e <kfun:kotlinx.serialization.json.internal#decodeSerializableValuePolymorphic@kotlinx.serialization.json.JsonDecoder(kotlinx.serialization.DeserializationStrategy><0:0>){0§<kotlin.Any?>}0:0 + 382
    at 7   Shared                              0x000000010ab7347a <kfun:kotlinx.serialization.json.Json#decodeFromString(kotlinx.serialization.DeserializationStrategy><0:0>;kotlin.String){0§<kotlin.Any?>}0:0 + 330
    at 8   Shared                              0x000000010abe42c3
b
It looks like the
json
object you are using to decode with is being shared between threads. Hence the mutability exception. Try creating a new
json
for each thread. Or do it all on one thread.
r
oh interesting, yeah, i was using the same instance of
Json
across all of my classes
so i should make a new one for each instance of my class then?
b
These days you can just use
Json.decodeFromString(string)
and not even create an instance at all, I think.
That works for version 1.1.0
r
well i want there to be some common settings setup for the
Json
instance like
ignoreUnknownKeys=true
b
Oh true, yeah, then I'd create a new one for each class / scope should be fine.
r
great, will give that a try, thank you 🙏🏻
👍 1
quick update on this. the way i fixed this was by using extension functions and always spinning up a new
Json
instance like so
Copy code
private fun getJson() = Json { ignoreUnknownKeys = true }

internal fun <T> String.fromJson(deserializer: DeserializationStrategy<T>): T {
    return getJson().decodeFromString(
        deserializer,
        this
    )
}