首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >为大型数据类创建自定义序列化程序

为大型数据类创建自定义序列化程序
EN

Stack Overflow用户
提问于 2022-07-17 13:33:03
回答 1查看 154关注 0票数 1

我有一个用于货币换算率响应的数据类。

我一直收到这个错误:拒绝调用、预期的76个参数寄存器、方法签名有78个或更多.

你可以在下面看到。( Conversion Rates类有超过160种货币)

我正在使用Ktor客户端,我的数据类如下所示:

代码语言:javascript
运行
复制
@Entity(tableName = "exchange")
@Serializable
data class Exchange(
    val base_code: String,
    @Contextual
    val conversion_rates: ConversionRates,
    val documentation: String,
    val result: String,
    val terms_of_use: String,
    @PrimaryKey
    val time_last_update_unix: Int,
    val time_last_update_utc: String,
    val time_next_update_unix: Int,
    val time_next_update_utc: String
)

@Serializable
data class ConversionRates(
    val AED: Double,
    val AFN: Double,
    val ALL: Double,
    val AMD: Double,
    val ANG: Double,
    val AOA: Double,
    val ARS: Double,
    val AUD: Double,
    val AWG: Double,
    val AZN: Double,
    val BAM: Double,
    val BBD: Double,
    val BDT: Double,
    val BGN: Double,
...

失败,例外: com.example.testingxml.data.models.ConversionRates$$serializer: com.example.testingxml.data.models.ConversionRates com.example.testingxml.data.models.ConversionRates$$serializer.deserialize(kotlinx.serialization.encoding.Decoder):验证器拒绝类java.lang.VerifyError无法验证: com.example.testingxml.data.models.ConversionRates com.example.testingxml.data.models.ConversionRates$$serializer.deserialize(kotlinx.serialization.encoding.Decoder):0x10F0拒绝调用,预期有76个参数寄存器,方法签名有78或更多( 'com.example.testingxml.data.models.ConversionRates$$serializer‘声明出现在/data/data/com.example.testingxml/code_cache/.overlay/base.apk/classes7.dex) 2022-07-17 16:23:27.926 8855-8855 AndroidRuntime com.example.testingxml E致命异常: main )中。

我试着用hashmap/ TreeMap.这不起作用,因为科特林无法对此做出反应。

有解决办法吗?

更新我得到的Json响应

代码语言:javascript
运行
复制
{
 "result":"success",
 "documentation":"https://www.exchangerate-api.com/docs",
 "terms_of_use":"https://www.exchangerate-api.com/terms",
 "time_last_update_unix":1658016002,
 "time_last_update_utc":"Sun, 17 Jul 2022 00:00:02 +0000",
 "time_next_update_unix":1658102402,
 "time_next_update_utc":"Mon, 18 Jul 2022 00:00:02 +0000",
 "base_code":"USD",
 "conversion_rates":{
  "USD":1,
  "AED":3.6725,
  "AFN":87.9897,
  "ALL":116.9156,
  "AMD":413.3227,
  "ANG":1.7900,
  "AOA":431.4219,
  "ARS":127.5711,
  "AUD":1.4762,
  "AWG":1.7900,
  "AZN":1.6932,
  "BAM":1.9426,
  "BBD":2.0000,
  "BDT":93.1628,
  "BGN":1.9427,
  "BHD":0.3760,
  "BIF":2032.0309,
  "BMD":1.0000,
  "BND":1.3978,
  "BOB":6.8633,
  "BRL":5.4199,
  "BSD":1.0000,
  "BTN":79.8199,
  "BWP":12.8324,
  "BYN":2.8230,
  "BZD":2.0000,
  "CAD":1.3050,
  "CDF":1988.6057,
  "CHF":0.9782,
  "CLP":1047.4250,
  "CNY":6.7686,
  "COP":4573.0573,
  "CRC":686.8741,
  "CUP":24.0000,
  "CVE":109.5198,
  "CZK":24.2810,
  "DJF":177.7210,
  "DKK":7.4100,
  "DOP":54.7252,
  "DZD":147.0795,
  "EGP":18.8746,
  "ERN":15.0000,
  "ETB":51.8192,
  "EUR":0.9932,
  "FJD":2.2271,
  "FKP":0.8452,
  "FOK":7.4100,
  "GBP":0.8452,
  "GEL":2.8469,
  "GGP":0.8452,
  "GHS":8.3242,
  "GIP":0.8452,
  "GMD":53.9357,
  "GNF":8643.2884,
  "GTQ":7.7432,
  "GYD":208.4165,
  "HKD":7.8518,
  "HNL":24.5589,
  "HRK":7.4836,
  "HTG":114.4866,
  "HUF":398.6438,
  "IDR":14976.7866,
  "ILS":3.4749,
  "IMP":0.8452,
  "INR":79.8209,
  "IQD":1454.0600,
  "IRR":42056.7004,
  "ISK":138.3686,
  "JEP":0.8452,
  "JMD":151.4748,
  "JOD":0.7090,
  "JPY":138.7800,
  "KES":117.9526,
  "KGS":81.3321,
  "KHR":4065.7093,
  "KID":1.4762,
  "KMF":488.6430,
  "KRW":1321.7446,
  "KWD":0.2996,
  "KYD":0.8333,
  "KZT":480.8824,
  "LAK":16868.6002,
  "LBP":1507.5000,
  "LKR":356.0525,
  "LRD":152.3277,
  "LSL":17.0698,
  "LYD":4.8552,
  "MAD":9.9367,
  "MDL":19.3046,
  "MGA":4084.1272,
  "MKD":61.1373,
  "MMK":1834.4490,
  "MNT":3130.7286,
  "MOP":8.0873,
  "MRU":36.7687,
  "MUR":44.7852,
  "MVR":15.4430,
  "MWK":1033.6225,
  "MXN":20.6318,
  "MYR":4.4398,
  "MZN":64.4837,
  "NAD":17.0698,
  "NGN":413.4387,
  "NIO":35.8600,
  "NOK":10.1891,
  "NPR":127.7119,
  "NZD":1.6266,
  "OMR":0.3845,
  "PAB":1.0000,
  "PEN":3.9116,
  "PGK":3.5170,
  "PHP":56.3397,
  "PKR":209.4856,
  "PLN":4.7442,
  "PYG":6855.2462,
  "QAR":3.6400,
  "RON":4.8888,
  "RSD":116.5282,
  "RUB":57.7811,
  "RWF":1058.9331,
  "SAR":3.7500,
  "SBD":8.0297,
  "SCR":13.0412,
  "SDG":461.6883,
  "SEK":10.5059,
  "SGD":1.3978,
  "SHP":0.8452,
  "SLE":13.6370,
  "SLL":13636.9704,
  "SOS":576.2883,
  "SRD":22.3936,
  "SSP":544.8830,
  "STN":24.3344,
  "SYP":2526.6716,
  "SZL":17.0698,
  "THB":36.6993,
  "TJS":10.4715,
  "TMT":3.4981,
  "TND":2.8755,
  "TOP":2.3438,
  "TRY":17.4168,
  "TTD":6.7612,
  "TVD":1.4762,
  "TWD":29.8712,
  "TZS":2320.8657,
  "UAH":31.0508,
  "UGX":3768.5019,
  "UYU":40.3063,
  "UZS":10908.3372,
  "VES":5.6990,
  "VND":23432.6566,
  "VUV":119.1620,
  "WST":2.7261,
  "XAF":651.5240,
  "XCD":2.7000,
  "XDR":0.7635,
  "XOF":651.5240,
  "XPF":118.5255,
  "YER":249.9997,
  "ZAR":17.0702,
  "ZMW":16.4457,
  "ZWL":395.1049
 }
}

产生错误的行。

代码语言:javascript
运行
复制
_exchangeRates.emit((it.data as Exchange).conversion_rates.toConversionItem())

我所犯的错误

com.example.testingxml.util.status.NetworkRequest$Success :无法转换为com.example.testingxml.data.models.Exchange java.lang.VerifyError:验证器拒绝了类com.example.testingxml.data.models.ConversionRates$$serializer: com.example.testingxml.data.models.ConversionRates com.example.testingxml.data.models.ConversionRates$$serializer.deserialize(kotlinx.serialization.encoding.Decoder),无法验证: com.example.testingxml.data.models.ConversionRates com.example.testingxml.data.models.ConversionRates$$serializer.deserialize(kotlinx.serialization.encoding.Decoder):0x10F0拒绝调用,预期的76个参数寄存器,方法签名有78个或更多( 'com.example.testingxml.data.models.ConversionRates$$serializer‘的声明出现在/data/data/com.example.testingxml/code_cache/.overlay/base.apk/classes7.dex)中无法删除dir '/data/data/com.example.testingxml/code_cache/.ll/':没有这样的文件或目录

更新2

我的Ktor客户:

代码语言:javascript
运行
复制
object Client {

    val client = HttpClient(Android) {
        install(Logging) {

            logger = object : Logger {
                override fun log(message: String) {
                    Log.d(KTOR_CLIENT_LOGGER, message)
                }
            }
            level = LogLevel.ALL
        }
        install(ContentNegotiation) {
            val converter = KotlinxSerializationConverter(Json {
                ignoreUnknownKeys = true
                prettyPrint = true
                isLenient = true
            })
            register(Json, converter)
            register(ContentType.Application.OctetStream, converter)
        }

        engine {
            socketTimeout = KTOR_TIMEOUT
            connectTimeout = KTOR_TIMEOUT
            sslManager = { HttpsURLConnection ->
                HttpsURLConnection.sslSocketFactory = SslSettings.getSslContext()!!.socketFactory
            }
        }
        defaultRequest {
            contentType(Json)
        }
    }
}

我的储藏室

代码语言:javascript
运行
复制
 override fun getAllFromApi(mainCurrency: String): Flow<RepositoryStatus> = flow {
        currencyApi.getCurrencyRate(mainCurrency).collect {networkRequest ->
            when (networkRequest) {
                is NetworkRequest.Failure -> emit(RepositoryStatus.Failure(networkRequest.error))
                is NetworkRequest.Success<*> -> emit(RepositoryStatus.Success(networkRequest))
            }
        }

    }.flowOn(Dispatchers.IO)

我的阿皮

代码语言:javascript
运行
复制
  override fun getCurrencyRate(mainCurrency: String): Flow<NetworkRequest> = flow {
        try {
            val result = client.get(Routes.Api.url.plus(mainCurrency))
            if (result.status == HttpStatusCode.OK) emit(NetworkRequest.Success(result.body<Exchange>()))
             else emit(NetworkRequest.Failure(result.toString()))
        }  catch  (e: ClientRequestException) {
            emit(NetworkRequest.Failure(e.message))
        } catch (e: ServerResponseException) {
            emit(NetworkRequest.Failure(e.message))
        } catch (e: IOException) {
            emit(NetworkRequest.Failure(e.localizedMessage!!))
        } catch (e: SerializationException) {
            emit(NetworkRequest.Failure(e.localizedMessage!!))
        }
    }.flowOn(Dispatchers.IO)
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-07-17 14:25:15

有一个已知臭虫,它具有自动序列化例程支持的最大字段数。

假设您有一个大型数据类(超过250个条目)来表示容器类中的嵌套对象(就像您拥有的那样):

代码语言:javascript
运行
复制
@Serializable
data class LargeData(
    val x1: String,
    val x2: String,
    val x3: String,
    val x4: String,
    //...
    val x258: String,
    val x259: String,
    val x260: String,
)

@Serializable
data class Container(
    val name: String,
    val rates: LargeData
)

当您尝试序列化/反序列化它时,会出现一个关于参数太多的错误。为了绕过它,您只需将数据存储在地图中,就可以处理无限的条目。

代码语言:javascript
运行
复制
@Serializable
data class Container(
    val name: String,
    val rates: Map<String,Double>
)

在您的示例中,您只需将大型ConversionRates数据类转换为一个映射,如下所示:

代码语言:javascript
运行
复制
@Serializable
data class Exchange(
    val base_code: String,
    val conversion_rates: Map<String,Double>, // change this line, and remove the ConversionRates data class
    val documentation: String,
    val result: String,
    val terms_of_use: String,
    @PrimaryKey
    val time_last_update_unix: Int,
    val time_last_update_utc: String,
    val time_next_update_unix: Int,
    val time_next_update_utc: String
)

如果您想将JSON部件与应用程序的其余部分隔离开来,您可以添加一个单元测试,它只接受一个JSON字符串,并检查它是否可以反序列化它

代码语言:javascript
运行
复制
class JSONUnitTest {
    private val testJson = "{\"name\":\"some name\"}"

    @Test
    fun testJson()  {
        val t2 = Json.decodeFromString<Exchange>(testJson)
        println(t2)
    }
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73012212

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档