3

我在 kotlinx JSON 序列化和在 Android 上使用 @Serializer 注释时遇到问题。该问题仅发生在某些 API 级别上 - 似乎在 API 级别 23 以上工作,并在下面给出此错误:

java.lang.VerifyError: Rejecting class org.kethereum.wallet.model.KdfSerializer because it failed compile-time verification (declaration of 'org.kethereum.wallet.model.KdfSerializer' appears in /data/app/package.name-1/base.apk:classes3.dex)
        at org.kethereum.wallet.model.WalletCrypto.write$Self(Wallet.kt)
        at org.kethereum.wallet.model.WalletCrypto$$serializer.save(Wallet.kt)
        at org.kethereum.wallet.model.WalletCrypto$$serializer.save(Wallet.kt:15)
        at kotlinx.serialization.KOutput.writeSerializableValue(Serialization.kt:146)
        at kotlinx.serialization.KOutput.writeSerializableElementValue(Serialization.kt:191)
        at org.kethereum.wallet.model.Wallet.write$Self(Wallet.kt)
        at org.kethereum.wallet.model.Wallet$$serializer.save(Wallet.kt)
        at org.kethereum.wallet.model.Wallet$$serializer.save(Wallet.kt:53)
        at kotlinx.serialization.KOutput.write(Serialization.kt:99)
        at kotlinx.serialization.json.JSON.stringify(JSON.kt:40)
        at kotlinx.serialization.json.JSON$Companion.stringify(JSON.kt:57)
        at org.kethereum.wallet.WalletFileKt.generateWalletFile(WalletFile.kt:30)

我为我的用例找到了一种解决方法——但我很想了解这个问题。这样做时:

@Serializable
data class WalletCrypto(
        var cipher: String,
        var ciphertext: String,
        var cipherparams: CipherParams,
        var kdf: String,
        @Serializable(with = KdfSerializer::class)
        var kdfparams: KdfParams,
        var mac: String) {

        object KdfSerializer : KSerializer<KdfParams> {
            override val serialClassDesc = SerialClassDescImpl("KDFSerializer")

            override fun load(input: KInput) = throw NotImplementedError("loading WalletCrypto is not implemented - use WalletCryptoForImport instead")

            override fun save(output: KOutput, obj: KdfParams) = when (obj) {
                        is ScryptKdfParams -> output.write(obj)
                        is Aes128CtrKdfParams -> output.write(obj)
                }
        }
}

代替:

@Serializable
data class WalletCrypto(
        var cipher: String,
        var ciphertext: String,
        var cipherparams: CipherParams,
        var kdf: String,
        @Serializable(with = KdfSerializer::class)
        var kdfparams: KdfParams,
        var mac: String) {

        @Serializer(forClass = KdfParams::class)
        object KdfSerializer : KSerializer<KdfParams> {
                override fun save(output: KOutput, obj: KdfParams) = when (obj) {
                        is ScryptKdfParams -> output.write(obj)
                        is Aes128CtrKdfParams -> output.write(obj)
                }
        }
}

问题消失了。所以问题似乎根源于使用@Serializer 注解。KdfParams 是一个密封类:

sealed class KdfParams {
    abstract var dklen: Int
    abstract var salt: String?
}
4

0 回答 0