Home > Blockchain >  RetroFit: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY in MVVM kotlin
RetroFit: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY in MVVM kotlin

Time:02-11

I was developing an app which make some networks call using Retrofit, and then load into a local database which Room.

My problem comes, when I try to implement the flow of the service which give all the reservations I made in the app, that throws me the title above error:

Regaring to the json which I would like to recover is this:

{
  "reservations": [
    {
      "id": "6204d5e99b251509d20d3e57",
      "garageSpotNumber": "91",
      "area": null,
      "employee": {
        "username": "[email protected]",
        "preferredName": "Luis Manuel Lucas Amate"
      },
      "detail": [
        {
          "id": "6204d5e99b251509d20d3e58",
          "date": 1644451200000
        }
      ],
      "dateFrom": 1644451200000,
      "dateTo": 1644451200000
    },
    {
      "id": "6204e0ad9b251509d20d3e59",
      "garageSpotNumber": "41",
      "area": null,
      "employee": {
        "username": "[email protected]",
        "preferredName": "Luis Manuel Lucas Amate"
      },
      "detail": [
        {
          "id": "6204e0ad9b251509d20d3e5a",
          "date": 1644537600000
        }
      ],
      "dateFrom": 1644537600000,
      "dateTo": 1644537600000
    },
    {
      "id": "6204e16c9b251509d20d3e5b",
      "garageSpotNumber": "43",
      "area": null,
      "employee": {
        "username": "[email protected]",
        "preferredName": "Luis Manuel Lucas Amate"
      },
      "detail": [
        {
          "id": "6204e16c9b251509d20d3e5c",
          "date": 1644796800000
        }
      ],
      "dateFrom": 1644796800000,
      "dateTo": 1644796800000
    },
    {
      "id": "6204e9dc9b251509d20d3e61",
      "garageSpotNumber": "60",
      "area": null,
      "employee": {
        "username": "[email protected]",
        "preferredName": "Luis Manuel Lucas Amate"
      },
      "detail": [
        {
          "id": "6204e9dc9b251509d20d3e62",
          "date": 1644883200000
        }
      ],
      "dateFrom": 1644883200000,
      "dateTo": 1644883200000
    },
    {
      "id": "6204e89b9b251509d20d3e5d",
      "garageSpotNumber": "47",
      "area": null,
      "employee": {
        "username": "[email protected]",
        "preferredName": "Luis Manuel Lucas Amate"
      },
      "detail": [
        {
          "id": "6204e89b9b251509d20d3e5e",
          "date": 1645056000000
        }
      ],
      "dateFrom": 1645056000000,
      "dateTo": 1645056000000
    },
    {
      "id": "6204e9929b251509d20d3e5f",
      "garageSpotNumber": "102",
      "area": null,
      "employee": {
        "username": "[email protected]",
        "preferredName": "Luis Manuel Lucas Amate"
      },
      "detail": [
        {
          "id": "6204e9929b251509d20d3e60",
          "date": 1645142400000
        }
      ],
      "dateFrom": 1645142400000,
      "dateTo": 1645142400000
    },
    {
      "id": "620519299b251509d20d3e63",
      "garageSpotNumber": "65",
      "area": null,
      "employee": {
        "username": "[email protected]",
        "preferredName": "Luis Manuel Lucas Amate"
      },
      "detail": [
        {
          "id": "620519299b251509d20d3e64",
          "date": 1645401600000
        }
      ],
      "dateFrom": 1645401600000,
      "dateTo": 1645401600000
    },
    {
      "id": "6205231a9b251509d20d3e65",
      "garageSpotNumber": "88",
      "area": null,
      "employee": {
        "username": "[email protected]",
        "preferredName": "Luis Manuel Lucas Amate"
      },
      "detail": [
        {
          "id": "6205231a9b251509d20d3e66",
          "date": 1645660800000
        }
      ],
      "dateFrom": 1645660800000,
      "dateTo": 1645660800000
    }
  ]
}

So my models and response are like this:

data class QueryGarageResponse(
    @SerializedName("reservations") var reservations: List<GarageBooking> = emptyList(),
    @SerializedName("error") var error: ErrorCall? = null
):Serializable


data class GarageBooking (
    @SerializedName("id") var id: String,
    @SerializedName("garageSpotNumber") var seatNumber : String,
    @SerializedName("area") var area:SeatArea,
    @SerializedName("employee") var employee: ReservedEmployee,
    @SerializedName("detail") var detail: BookingDetail,
    @SerializedName("dateFrom") var dateFrom: Long,
    @SerializedName("dateTo") var dateTo: Long
    ):Serializable

Regarding to my api services:

 @GET("api/v1/garageReservation")
    fun getAllGarageReservations(
        @Header("tokenGraph")token:String,
        @Query("startdate")startDate:Long,
        @Query("finishDate")finishDate:Long,
        @Query("employee")employee:String
    ):Call<QueryGarageResponse>

my repository:

SeatRepository.kt

fun getAllGarageReservations(
        token:String,
        startDate: Long,
        finishDate:Long,
        employee:String
    ): LiveData<QueryGarageResponse>{
        var responseData = MutableLiveData<QueryGarageResponse>()

        api.getAllGarageReservations(token, startDate, finishDate, employee)
            .enqueue(object: Callback<QueryGarageResponse> {
                override fun onResponse(
                    call: Call<QueryGarageResponse>,
                    response: Response<QueryGarageResponse>
                ) {
                    Log.d("garage", "resp getAllGarageReservation repository: $response")
                    if(response.isSuccessful){
                        Log.d("garage", "resp repository: ${response.body()}")
                        responseData.value = response.body()
                    }else{
                        try {
                            val apiError = getErrorApi(response.errorBody()!!, ApiError::class.java)

                            apiError.error.let {
                                responseData.value =
                                    QueryGarageResponse(
                                        reservations = ArrayList(),
                                        error = ErrorCall(
                                            status = it.status,
                                            payload = it.payload.seat
                                        )
                                    )
                            }


                        } catch (ex: Exception) {
                            responseData.value =
                                QueryGarageResponse(
                                    reservations = ArrayList(),
                                    error = ErrorCall(
                                       message = ex.message!!
                                    )
                                )
                        }
                    }

                }

                override fun onFailure(call: Call<QueryGarageResponse>, t: Throwable) {
                    responseData.value =
                        QueryGarageResponse(
                           reservations = arrayListOf(),
                           error = ErrorCall(message = t.message!!)
                        )
                    }
            })
        return responseData
    }

My viewModel

CheckGarageViewModel.kt

class CheckGarageViewModel(
    private val repository : SeatsRepository
    ): ViewModel() {

    fun getGarageBookings(): LiveData<QueryGarageResponse>{
        //1296000000 = millisegundos equivalentes a 15 dias.
        return repository.getAllGarageReservations(token = UserPreferences.prefs.token!!, System.currentTimeMillis(), System.currentTimeMillis()   1296000000, UserPreferences.prefs.email!!)
    }

}

I don't know why this error happens when I really expect an Array instead of an object.

So if you can help take thanks in advance !

CodePudding user response:

You are facing an error because you are parsing the wrong data type.

data class GarageBooking (
    @SerializedName("id") var id: String,
    @SerializedName("garageSpotNumber") var seatNumber : String,
    @SerializedName("area") var area:SeatArea,
    @SerializedName("employee") var employee: ReservedEmployee,
    @SerializedName("detail") var detail: BookingDetail,
    @SerializedName("dateFrom") var dateFrom: Long,
    @SerializedName("dateTo") var dateTo: Long
):Serializable

According to this model class, detail variable should be Object in API response. But have a look at the API response you have added.

{
  "id": "6204e89b9b251509d20d3e5d",
  "garageSpotNumber": "47",
  "area": null,
  "employee": {
    "username": "[email protected]",
    "preferredName": "Luis Manuel Lucas Amate"
  },
  "detail": [
    {
      "id": "6204e89b9b251509d20d3e5e",
      "date": 1645056000000
    }
  ],
  "dateFrom": 1645056000000,
  "dateTo": 1645056000000
}

detail variable is Array type. So you need to define detail variable as a list in your model class like below,

    @SerializedName("detail") var detail: List<BookingDetail>?,

After making this change, your app will run without error.

  • Related