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