我在 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?
}