Hi I'm use Kotlin retrofit and moshi I have that JSON
[
{
"id": "bitcoin",
"symbol": "btc",
"name": "Bitcoin",
"image": "https://assets.coingecko.com/coins/images/1/large/bitcoin.png?1547033579",
"current_price": 21917,
"market_cap": 418101666154,
"market_cap_rank": 1,
"fully_diluted_valuation": 459616529150,
"total_volume": 35275748678,
"high_24h": 22967,
"low_24h": 21800,
"price_change_24h": -785.2614865719079,
"price_change_percentage_24h": -3.4589,
"market_cap_change_24h": -16487597586.019958,
"market_cap_change_percentage_24h": -3.79383,
"circulating_supply": 19103175,
"total_supply": 21000000,
"max_supply": 21000000,
"ath": 69045,
"ath_change_percentage": -68.28207,
"ath_date": "2021-11-10T14:24:11.849Z",
"atl": 67.81,
"atl_change_percentage": 32195.96528,
"atl_date": "2013-07-06T00:00:00.000Z",
"roi": null,
"last_updated": "2022-07-25T18:38:56.019Z"
},
{
"id": "ethereum",
"symbol": "eth",
"name": "Ethereum",
"image": "https://assets.coingecko.com/coins/images/279/large/ethereum.png?1595348880",
"current_price": 1522.52,
"market_cap": 181649214301,
"market_cap_rank": 2,
"fully_diluted_valuation": null,
"total_volume": 17695232530,
"high_24h": 1651.4,
"low_24h": 1510.24,
"price_change_24h": -72.84932292922076,
"price_change_percentage_24h": -4.56629,
"market_cap_change_24h": -10281152619.016693,
"market_cap_change_percentage_24h": -5.35671,
"circulating_supply": 119829051.14353,
"total_supply": 119829051.14353,
"max_supply": null,
"ath": 4878.26,
"ath_change_percentage": -68.9122,
"ath_date": "2021-11-10T14:24:19.604Z",
"atl": 0.432979,
"atl_change_percentage": 350158.16453,
"atl_date": "2015-10-20T00:00:00.000Z",
"roi": {
"times": 91.78338127800683,
"currency": "btc",
"percentage": 9178.338127800684
},
"last_updated": "2022-07-25T18:39:03.483Z"
},
{
"id": "tether",
"symbol": "usdt",
"name": "Tether",
"image": "https://assets.coingecko.com/coins/images/325/large/Tether-logo.png?1598003707",
"current_price": 1.001,
"market_cap": 65934603930,
"market_cap_rank": 3,
"fully_diluted_valuation": null,
"total_volume": 49334676401,
"high_24h": 1.011,
"low_24h": 0.996453,
"price_change_24h": 0.00015041,
"price_change_percentage_24h": 0.01503,
"market_cap_change_24h": 33333966,
"market_cap_change_percentage_24h": 0.05058,
"circulating_supply": 65876317670.4762,
"total_supply": 65876317670.4762,
"max_supply": null,
"ath": 1.32,
"ath_change_percentage": -24.34669,
"ath_date": "2018-07-24T00:00:00.000Z",
"atl": 0.572521,
"atl_change_percentage": 74.83471,
"atl_date": "2015-03-02T00:00:00.000Z",
"roi": null,
"last_updated": "2022-07-25T18:36:04.706Z"
}
]
So I make a 2 classes
data class TopCrypto(
val cryptos: List<CryptoStock>? = null
)
and
data class CryptoStock(
val id: String? = null,
val symbol: String? = null,
val image: String? = null,
val currentPrice: String? = null,
val priceChange: Double? = null
)
i try use Call<List> but it's not what i want. I'd like to have respons in TopCrypto
interface CryptoService {
@GET("coins/markets")
fun getTopCrypto(@Query("vs_currency") vsCurrency:String,
@Query("per_page") limit: Int,
@Query("order") order:String = "market_cap_desc"
): Call<TopCrypto>
}
object
object Api {
private val BASE_URL = "https://api.coingecko.com/api/v3/"
private val moshi = Moshi.Builder()
.add(KotlinJsonAdapterFactory())
.build()
private val retrofit = Retrofit.Builder()
.addConverterFactory(MoshiConverterFactory.create(moshi))
.baseUrl(BASE_URL)
.build()
val retrofitService: CryptoService by lazy{
retrofit.create(CryptoService::class.java)
}
}
class CryptoManager {
init {
getCryptos()
}
private val _cryptoResponse = mutableStateOf(TopCrypto())
val cryptoResponse: State<TopCrypto>
@Composable get() = remember {
_cryptoResponse
}
private fun getCryptos(){
val service = Api.retrofitService.getTopCrypto("usd",10)
service.enqueue(object : Callback<TopCrypto> {
override fun onResponse(call: Call<TopCrypto>, response: Response<TopCrypto>) {
if (response.isSuccessful){
_cryptoResponse.value = response.body()!!
Log.d("crypto","${_cryptoResponse.value}")
}else{
Log.d("error","${response.errorBody()}")
}
}
override fun onFailure(call: Call<TopCrypto>, t: Throwable) {
Log.d("error","${t.message}")
}
})
}
}
For now i have Expected BEGIN_OBJECT but was BEGIN_ARRAY at path $. I know i must map somehow Json array to my class TopCrypto Thanks in advance for help :)
CodePudding user response:
I do like Eric and Jorn said :). Remove class TopCrypto and change
CryptoManager class
class CryptoManager {
init {
getCryptos()
}
private val _cryptoResponse = mutableStateOf(CryptoStock())
val cryptoResponse: MutableState<CryptoStock>
@Composable get() = remember {
_cryptoResponse
}
private fun getCryptos(){
val service = Api.retrofitService.getTopCrypto("usd",5)
service.enqueue(object : Callback<List<CryptoStock>>
{
override fun onResponse(call: Call<List<CryptoStock>>, response: Response<List<CryptoStock>>) {
if (response.isSuccessful){
Log.d("apiHeaders","${response.headers()}")
Log.d("apiBody","${response.body()}")
}else{
Log.d("error","${response.errorBody()}")
}
}
override fun onFailure(call: Call<List<CryptoStock>>, t: Throwable) {
Log.e("TAG", "login() - onFailure() ", t)
}
})
}
and inteface
interface CryptoService {
@GET("coins/markets")
fun getTopCrypto(@Query("vs_currency") vsCurrency:String,
@Query("per_page") limit: Int,
@Query("order") order:String = "market_cap_desc"
): Call<List<CryptoStock>>
}
CodePudding user response:
Problem is in creating data class from JSON string. Your data class TopCrypto requires object but response json string has list so I have tried to modify data class, Can you please try below data class once
class TopCrypto : ArrayList<TopCrypto.TopCryptoData>(){
data class TopCryptoData(
val ath: Double,
val ath_change_percentage: Double,
val ath_date: String,
val atl: Double,
val atl_change_percentage: Double,
val atl_date: String,
val circulating_supply: Double,
val current_price: Double,
val fully_diluted_valuation: Long,
val high_24h: Double,
val id: String,
val image: String,
val last_updated: String,
val low_24h: Double,
val market_cap: Long,
val market_cap_change_24h: Double,
val market_cap_change_percentage_24h: Double,
val market_cap_rank: Int,
val max_supply: Int,
val name: String,
val price_change_24h: Double,
val price_change_percentage_24h: Double,
val roi: Roi,
val symbol: String,
val total_supply: Double,
val total_volume: Long
) {
data class Roi(
val currency: String,
val percentage: Double,
val times: Double
)
}
}