kotlin 改型+莫希定制适配器

31moq8wy  于 2022-12-30  发布在  Kotlin
关注(0)|答案(1)|浏览(171)

我很难理解如何用莫希转换JSON数据。我正在学习Android和Kotlin,我的应用程序应该加载和显示COVID数据。输入的JSON格式如下:

[
  {
    "infected": 109782,
    "tested": "NA",
    "recovered": 75243,
    "deceased": 2926,
    "country": "Algeria",
    "moreData": "https://api.apify.com/v2/key-value-stores/pp4Wo2slUJ78ZnaAi/records/LATEST?disableRedirect=true",
    "historyData": "https://api.apify.com/v2/datasets/hi0DJXpcyzDwtg2Fm/items?format=json&clean=1",
    "sourceUrl": "https://www.worldometers.info/coronavirus/",
    "lastUpdatedApify": "2021-02-11T12:15:00.000Z"
  },
  {
    "infected": 425561,
    "tested": 11205451,
    "recovered": 407155,
    "deceased": 8138,
    "country": "Austria",
    "moreData": "https://api.apify.com/v2/key-value-stores/RJtyHLXtCepb4aYxB/records/LATEST?disableRedirect=true",
    "historyData": "https://api.apify.com/v2/datasets/EFWZ2Q5JAtC6QDSwV/items?format=json&clean=1",
    "sourceUrl": "https://www.sozialministerium.at/Informationen-zum-Coronavirus/Neuartiges-Coronavirus-(2019-nCov).html",
    "lastUpdatedApify": "2021-02-11T12:15:00.000Z"
  },
...
]

正如你所看到的,数字也可以用字符串来表示(如“tested”),而且一些国家的URL可能会丢失,所以我按照莫希文档创建了2个数据类和一个自定义适配器。

//desired structure
data class CountryData(
    val infected: Int,
    val tested: Int,
    val recovered: Int,
    val deceased: Int,
    val country: String,
    val moreData: String,
    val historyData: String,
    val sourceUrl: String,
    val lastUpdatedApify: String
)

//actual JSON
data class CountryDataJson(
    val infected: String,
    val tested: String,
    val recovered: String,
    val deceased: String,
    val country: String,
    val moreData: String?,
    val historyData: String?,
    val sourceUrl: String?,
    val lastUpdatedApify: String
)

自定义适配器:

import android.util.Log
import com.example.coronastats.network.CountryData
import com.example.coronastats.network.CountryDataJson
import com.squareup.moshi.FromJson

class CountryJsonAdapter {
    @FromJson fun fromJson(countryDataJson: CountryDataJson): CountryData {
        val countryData = CountryData(
            if (countryDataJson.infected != "NA") countryDataJson.infected.toInt() else -1,
            if (countryDataJson.tested != "NA") countryDataJson.tested.toInt() else -1,
            if (countryDataJson.recovered != "NA") countryDataJson.recovered.toInt() else -1,
            if (countryDataJson.deceased != "NA") countryDataJson.deceased.toInt() else -1,
            countryDataJson.country,
            countryDataJson.moreData ?: "NA",
            countryDataJson.historyData ?: "NA",
            countryDataJson.sourceUrl ?: "NA",
            countryDataJson.lastUpdatedApify
        )
        Log.d("adapterLOG", "fromJson triggered")
        return countryData
    }
}

我的服务API:

import com.example.coronastats.CountryJsonAdapter
import com.squareup.moshi.Moshi
import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory
import retrofit2.Retrofit
import retrofit2.converter.moshi.MoshiConverterFactory
import retrofit2.http.GET

private const val BASE_URL = "https://api.apify.com/"

private val moshi = Moshi.Builder()
    .add(CountryJsonAdapter())
    .build()

private val retrofit = Retrofit.Builder()
    .addConverterFactory(MoshiConverterFactory.create(moshi))
    .baseUrl(BASE_URL)
    .build()

interface CoronaApiService {
    @GET("v2/key-value-stores/tVaYRsPHLjNdNBu7S/records/LATEST?disableRedirect=true")
    suspend fun getStatistics() : List<CountryData>
}

object CoronaApi {
    val retrofitService: CoronaApiService by lazy {
        retrofit.create(CoronaApiService::class.java)
    }
}

结果我得到了一个空的屏幕,适配器中的日志从来没有被触发过,所以我假设出了什么问题,我的适配器从来没有被调用过。
NB:如果没有这些转换器的东西,应用程序可以使用标准的KotlinJsonAdapterFactory()和CountryData类作为所有字符串运行,但我想知道如何获得这里的结构。

goqiplq2

goqiplq21#

我认为CountryDataJson缺少默认值。阅读文档时,我注意到以下问题:
在Kotlin中,如果这些字段位于主构造函数中,则它们必须具有默认值。

相关问题