0

Recently I have been working on project which includes working with API. I have checked it in Postman and I am sure that its response is an Array of Objects but when tried to use it I faced Expected BEGIN_OBJECT but was BEGIN_ARRAY error so I changed the API response type to List to see what happens and I realized instead of Array of objects it returns Arrays of object's arrays and in all of them objects are null and have no valid response.

fun createApiService(): ApiService {

    val client = OkHttpClient.Builder()
        .addInterceptor(
            BasicAuthInterceptor(
                "username",
                "password"
            )
        )
        .build()


    val api = Retrofit.Builder()
        .baseUrl(BASE_URL)
        .client(client)
        .addConverterFactory(GsonConverterFactory.create())
        .build()

    return api.create(ApiService::class.java)

}

class BasicAuthInterceptor(username: String, password: String) : Interceptor {
    private var credentials: String = Credentials.basic(username, password)

    override fun intercept(chain: Interceptor.Chain): okhttp3.Response {
        var request = chain.request()
        request = request.newBuilder().header("Authorization", credentials).build()
        return chain.proceed(request)
    }
}

This part is for creating API and giving it username and password because it is private and it needs Authorization:

data class ProductResponse(
    val products: List<Product>
)

data class Product(

     /// its attributes are here

    )
interface ApiService {

    @GET("products")
    suspend fun getAllProducts(): List<ProductResponse>

}
class ProductRepositoryImpl(
    private val apiService: ApiService,
) : ProductRepository {
    override suspend fun getProducts(isInternetConnected: Boolean): List<Product> {
        val dataFromServer = apiService.getAllProducts()
        Log.v("api",dataFromServer.toString())
        return dataFromServer[0].products
    }
}

and Log shows:

[ProductResponse(products=null), ProductResponse(products=null), ProductResponse(products=null), ProductResponse(products=null), ProductResponse(products=null), ProductResponse(products=null), ProductResponse(products=null), ProductResponse(products=null), ProductResponse(products=null), ProductResponse(products=null)]

[{
    "name": "test",
    "type": "simple",
    "featured": false,
    "catalog_visibility": "visible",
    "description": "",
    "short_description": "",
    "price": "351000",
    "regular_price": "351000",
    "sale_price": "",
    "on_sale": false,
    "purchasable": true,
    "total_sales": 0,
    "button_text": "",
    "tax_status": "taxable",
    "tax_class": "",
    "manage_stock": false,
    "stock_quantity": null,
    "backorders": "no",
    "backorders_allowed": false,
    "backordered": false,
    "low_stock_amount": null,
    "sold_individually": false,
    "weight": "",
    "shipping_required": true,
    "shipping_taxable": true,
    "shipping_class": "",
    "shipping_class_id": 0,
    "reviews_allowed": true,
    "average_rating": "0.00",
    "rating_count": 0,
    "parent_id": 0,
    "purchase_note": "",
   
and it continues like this and is more than 600 lines
12
  • You should include the JSON you're trying to parse, because your attempt to describe it is quite confusing ("Arrays of object's arrays" ... what?) Commented May 8, 2024 at 19:11
  • @dominicoder I mean as I expect it should return only one ProductResponse with products in it but it is returning an array which includes 10 ProductResponse and each of my JSON objects are near 600 lines and it is not possible to share them Commented May 9, 2024 at 7:29
  • Well share a simplified version of the JSON showing the main structure, you don't have to include every single object. Commented May 9, 2024 at 16:40
  • @dominicoder I added a part of my JSON Object as you wished but it has many other thing inside like an array for images and .... Commented May 10, 2024 at 4:58
  • That Json represents a single Object. Your api is trying to get a List<Product>(i.e., a Json Array[ { "key": "value" }, { "key": "value" }, etc ... ]. Hence your error. Make your backend return an array or make your client code return a singular object. Commented May 10, 2024 at 5:02

1 Answer 1

0

The return type of your ApiService methods should directly be the desired response type (or it can be wrapped inside a retrofit2.Response, e.g. Response<MyClass>). There is no need for the separate ProductResponse class you have, which just holds the actual response data.

So since your API returns a JSON array, your service method should have List<...> as return type (or any other type which Gson can deserialize from a JSON array).

The reason why you are getting a lot of ProductResponse(products=null) is that you have specified List<ProductResponse> as return type. So Gson expects the following JSON structure:

[
  {
    "products": [
      { ... },
      ...
    ]
  },
  {
    "products": [
      { ... },
      ...
    ]
  },
  ...
]

(and because Gson ignores missing fields, ProductResponse#products simply remains null)

To solve this, change the return type of getAllProducts and delete the ProductResponse class:

@GET("products")
suspend fun getAllProducts(): List<Product>
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.