skip to Main Content

I’m trying to read the following data from the API:

[
    [
        1724180400000,
        "59191.45000000",
        "59597.28000000",
        "59137.78000000",
        "59511.99000000",
        "544.56764000",
        1724183999999,
        "32351755.73378980",
        51002,
        "290.20494000",
        "17241827.16012430",
        "0"
    ],
    [
        1724184000000,
        "59512.00000000",
        "59722.72000000",
        "59421.38000000",
        "59589.07000000",
        "301.58055000",
        1724187599999,
        "17968010.37382020",
        23563,
        "169.48375000",
        "10099057.30721750",
        "0"
    ]
]

But Retrofit expects a JSON response starting with ‘{‘ instead of ‘[‘.

I tried serializing the data with the following dependencies:

implementation(libs.retrofit)
implementation(libs.retrofit2.kotlinx.serialization.converter)
implementation(libs.okhttp)
implementation(libs.kotlinx.serialization.json)

When I tell Retrofit to expect a list with lists it states that ‘Serializer for class ‘Any’ is not found’. How to serialize this response type with only arrays containing mixed types (String and Int)?

2

Answers


  1. Chosen as BEST ANSWER

    The answers in this thread helped a lot to understand and solve the problem. In my Android app I implemented the solution like this:

    In the api service (Retrofit 2 interface)

    @GET("klines.json")
    suspend fun getKlines(): List<List<JsonPrimitive>>
    

    In the network repository, fetch and convert the rawJson to my custom Kline class

    override suspend fun getKlines(): List<Kline> {
        val rawJson = apiService.getKlines()
        return rawJson.map { data ->
            Kline(
                timestamp = data[0].long,
                open = data[1].double,
                high = data[2].double,
                low = data[3].double,
                close = data[4].double,
                volume = data[5].double,
                closeTime = data[6].long,
                quoteAssetVolume = data[7].double,
                numberOfTrades = data[8].int,
                takerBuyBaseAssetVolume = data[9].double,
                takerBuyQuoteAssetVolume = data[10].double
            )
        }
    }
    

    The Call type was not needed in my scenario because the functions are called from within a coroutine scope.

    The rawJson result in logcat:

    [[1724151600000, "60716.01000000", "60734.91000000", "60401.90000000", "60518.82000000", "1086.55870000", 1724155199999, "65807817.60717790", 58639, "538.35193000", "32602791.90598670", "0"], [...] ] 
    

    This implementation works for me, but better solutions are appreciated!


  2. If type does not matter, you can just use type String.

    @GET("test")
    fun test(): Call<List<List<String>>>
    

    If type matters, you can use JsonPrimitive.

    @GET("test")
    fun test(): Call<List<List<JsonPrimitive>>>
    

    After you received data, you can parse it as List<List<Any>> like this.

    val result: List<List<JsonPrimitive>> = response.body()!!
    
    val parsedResult: List<List<Any>> = result.map { innerItem ->
        innerItem.map {
             if (it.isNumber) it.asInt
             else it.asString
        }
    }
    
    println(parsedResult)
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search