Thread
#serialization
    Justin

    Justin

    3 years ago
    I recently experienced a crash on iOS with the following message:
    Instances of kotlin.Error, kotlin.RuntimeException and subclasses aren't propagated from Kotlin to Objective-C/Swift.
    
    Other exceptions can be propagated as NSError if method has or inherits @Throws annotation.
    
    Uncaught Kotlin exception: kotlinx.serialization.MissingFieldExcpetion: Field 'deviceId' is required, but it was missing
    As the message suggests, the KMP library failed to deserialize to:
    @Serializable data class Details(val id: String, val deviceId: String)
    ...because the JSON string didn't contain a
    deviceId
    field, hence the crash on the iOS app using the library. I have already fixed this specific crash by modifying the model as follows:
    @Serializable data class Details(val id: String, val deviceId: String? = null)
    But my question is this: Is there a way to have
    kotlinx.serialization
    propagate any/all exceptions it throws to the implementing platform (iOS/Android/Web/etc.) to decide how to handle it? In this case, it would have been preferable to have caught this error in iOS, logged it using the iOS logging service, and not-crashed. Any ideas would be much appreciated, thanks!
    s

    Sam

    3 years ago
    I'm not going to claim that this is the best idea but it has worked for me. I use a custom sealedResult class for kotlin code that can generate an exception. The exceptions are caught and then returned in a Result.Failure object. For my iOS code, I have some extension functions on Result.Failure that will convert the Exception to an
    NSError
    The Result class is a stripped down version of the one found at https://github.com/michaelbull/kotlin-result. The extension to make an
    NSError
    object isn't too complicated though you probably want to make other extensions for your own custom exceptions.
    fun <V, E : Error> Result<V, E>.nserrorOrNull(): NSError? {
        val err = this.failureOrNull() ?: return null
        val localizedDescription = err.message
        val userInfo = mapOf<Any?, Any?>(NSLocalizedDescriptionKey to localizedDescription)
        return NSError("my app core", -20, userInfo)
    }
    s

    sandwwraith

    3 years ago
    I've created an issue for that: https://github.com/Kotlin/kotlinx.serialization/issues/564 I'll see what can be done. Probably annotating all
    StringFormat
    members with
    @Throws
    would be enough to solve the problem