Kotlin - java.lang.IllegalStateExpection: Expected BEGIN_ARRAY but was STRING - android

I faced with this problem. I've searched in the internet but answers was for Java, not Kotlin. How do i solve this ? If you need anything else please let me know. I'm trying to get closest restaurants for user location. Currently I'm using static variables because I couldn't get Zomato APi yet. How can i manage to do this ? It's been 4-5 days since I start learning kotlin
My restaurant data class
data class Restaurant(
#SerializedName("name")
val restName: String?,
#SerializedName("address")
val restAddress: String?
)
My API interface
interface ZomatoAPI {
#Headers(
"Accept: application/json",
"user-key: $API_KEY"
)
#GET("/search")
fun getRestaurants(#Query("count") count: Int
,#Query("lat") latitude: Double
,#Query("lon") longitude: Double
,#Query("sort") sort : String
,#Query("order") order : String
): Single<List<Restaurant>>
}
My Service Class
class RestaurantService{
private val baseUrl = "https://developers.zomato.com/api/v2.1/"
private val api: ZomatoAPI
private val latitude = 41.2
private val longitude = 28.2
init {
api = Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create(GsonBuilder().setLenient().create()))
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build()
.create(ZomatoAPI::class.java)
}
fun getRestaurants(): Single<List<Restaurant>>{
return api.getRestaurants(5,latitude,longitude,"rating","desc")
}
}
My ListViewModel
class ListViewModel: ViewModel(){
private val restaurantService = RestaurantService()
private val disposable = CompositeDisposable()
val restaurants = MutableLiveData<List<Restaurant>>()
val restaurantLoadError = MutableLiveData<Boolean>()
val loading = MutableLiveData<Boolean>()
fun refresh() {
fetchRestaurants()
}
private fun fetchRestaurants() {
loading.value = true
restaurantService.getRestaurants()
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribeWith(object: DisposableSingleObserver<List<Restaurant>>(){
override fun onSuccess(value: List<Restaurant>?) {
restaurants.value = value
restaurantLoadError.value = false
loading.value = false
}
override fun onError(e: Throwable?) {
restaurantLoadError.value = true
loading.value = false
}
})
}
override fun onCleared() {
super.onCleared()
disposable.clear()
}
}
Response Body of Zomato API
{
"results_found": 1499579,
"results_start": 0,
"results_shown": 2,
"restaurants": [
{
"restaurant": {
"R": {
"has_menu_status": {
"delivery": -1,
"takeaway": -1
},
"res_id": 18047914,
"is_grocery_store": false
},
"apikey": "61528551ffc800703d600cb2c25e6900",
"id": "18047914",
"name": "The Mossy Cafe",
"url": "https://www.zomato.com/mossy-point-nsw/the-mossy-cafe-mossy-point?utm_source=api_basic_user&utm_medium=api&utm_campaign=v2.1",
"location": {
"address": "31 Pacific Street, Mossy Point",
"locality": "Mossy Point",
"city": "Mossy Point",
"city_id": 2181,
"latitude": "-35.8369730000",
"longitude": "150.1796610000",
"zipcode": "",
"country_id": 14,
"locality_verbose": "Mossy Point, Mossy Point"
},
"switch_to_order_menu": 0,
"cuisines": "Cafe Food, Coffee and Tea",
"timings": "7:30am – 3pm (Mon-Sun)",
"average_cost_for_two": 50,
"price_range": 4,
"currency": "$",
"highlights": [
"Cash",
"Debit Card",
"No Alcohol Available",
"Credit Card",
"Breakfast",
"Lunch",
"Kid Friendly",
"Vegan Options",
"Pet Friendly",
"Indoor Seating",
"Gluten Free Options"
],
"offers": [],
"opentable_support": 0,
"is_zomato_book_res": 0,
"mezzo_provider": "OTHER",
"is_book_form_web_view": 0,
"book_form_web_view_url": "",
"book_again_url": "",
"thumb": "",
"user_rating": {
"aggregate_rating": "3.9",
"rating_text": "Good",
"rating_color": "9ACD32",
"rating_obj": {
"title": {
"text": "3.9"
},
"bg_color": {
"type": "lime",
"tint": "600"
}
},
"votes": 7
},
"all_reviews_count": 0,
"photos_url": "https://www.zomato.com/mossy-point-nsw/the-mossy-cafe-mossy-point/photos?utm_source=api_basic_user&utm_medium=api&utm_campaign=v2.1#tabtop",
"photo_count": 42,
"menu_url": "https://www.zomato.com/mossy-point-nsw/the-mossy-cafe-mossy-point/menu?utm_source=api_basic_user&utm_medium=api&utm_campaign=v2.1&openSwipeBox=menu&showMinimal=1#tabtop",
"featured_image": "",
"has_online_delivery": 0,
"is_delivering_now": 0,
"store_type": "",
"include_bogo_offers": true,
"deeplink": "zomato://restaurant/18047914",
"is_table_reservation_supported": 0,
"has_table_booking": 0,
"events_url": "https://www.zomato.com/mossy-point-nsw/the-mossy-cafe-mossy-point/events#tabtop?utm_source=api_basic_user&utm_medium=api&utm_campaign=v2.1",
"phone_numbers": "02 4471 8599",
"all_reviews": {
"reviews": []
},
"establishment": [
"Café"
],
"establishment_types": []
}
},
{
"restaurant": {
"R": {
"has_menu_status": {
"delivery": -1,
"takeaway": -1
},
"res_id": 16611721,
"is_grocery_store": false
},
"apikey": "61528551ffc800703d600cb2c25e6900",
"id": "16611721",
"name": "Blue Swimmer at Seahaven",
"url": "https://www.zomato.com/gerroa-nsw/blue-swimmer-at-seahaven-gerroa?utm_source=api_basic_user&utm_medium=api&utm_campaign=v2.1",
"location": {
"address": "19 Riverleigh Ave, Gerroa, Gerroa",
"locality": "Gerroa",
"city": "Gerroa",
"city_id": 2154,
"latitude": "-34.7697390000",
"longitude": "150.8117400000",
"zipcode": "2534",
"country_id": 14,
"locality_verbose": "Gerroa, Gerroa"
},
"switch_to_order_menu": 0,
"cuisines": "Modern Australian, Australian",
"timings": "7 AM to 3 PM (Mon, Tue, Wed, Thu, Sun), 7 AM to 3 PM, 5:30 PM to 11 PM (Fri-Sat)",
"average_cost_for_two": 20,
"price_range": 2,
"currency": "$",
"highlights": [
"Cash",
"Breakfast",
"Lunch",
"No Alcohol Available",
"Dinner",
"Table booking recommended",
"Outdoor Seating"
],
"offers": [],
"opentable_support": 0,
"is_zomato_book_res": 0,
"mezzo_provider": "OTHER",
"is_book_form_web_view": 0,
"book_form_web_view_url": "",
"book_again_url": "",
"thumb": "",
"user_rating": {
"aggregate_rating": "3.9",
"rating_text": "Good",
"rating_color": "9ACD32",
"rating_obj": {
"title": {
"text": "3.9"
},
"bg_color": {
"type": "lime",
"tint": "600"
}
},
"votes": 21
},
"all_reviews_count": 11,
"photos_url": "https://www.zomato.com/gerroa-nsw/blue-swimmer-at-seahaven-gerroa/photos?utm_source=api_basic_user&utm_medium=api&utm_campaign=v2.1#tabtop",
"photo_count": 15,
"menu_url": "https://www.zomato.com/gerroa-nsw/blue-swimmer-at-seahaven-gerroa/menu?utm_source=api_basic_user&utm_medium=api&utm_campaign=v2.1&openSwipeBox=menu&showMinimal=1#tabtop",
"featured_image": "",
"has_online_delivery": 0,
"is_delivering_now": 0,
"store_type": "",
"include_bogo_offers": true,
"deeplink": "zomato://restaurant/16611721",
"is_table_reservation_supported": 0,
"has_table_booking": 0,
"events_url": "https://www.zomato.com/gerroa-nsw/blue-swimmer-at-seahaven-gerroa/events#tabtop?utm_source=api_basic_user&utm_medium=api&utm_campaign=v2.1",
"phone_numbers": "(02) 4234 3796",
"all_reviews": {
"reviews": [
{
"review": []
},
{
"review": []
},
{
"review": []
},
{
"review": []
},
{
"review": []
}
]
},
"establishment": [
"Casual Dining"
],
"establishment_types": []
}
}
]
}

Your getRestaurants method should be like this:
interface ZomatoAPI {
#Headers(
"Accept: application/json",
"user-key: $API_KEY"
)
#GET("/search")
fun getRestaurants(#Query("count") count: Int
,#Query("lat") latitude: Double
,#Query("lon") longitude: Double
,#Query("sort") sort : String
,#Query("order") order : String
): Single<RestaurantResponse>
}
and your model class should be like this,
data class RestaurantResponse(
#SerializedName("restaurants")
val restaurants: List<Restaurant>?,
#SerializedName("results_found")
val results_found: Int?
#SerializedName("results_start")
val results_start: Int?
#SerializedName("results_shown")
val results_shown: Int?
)

Related

PID: 18319 java.lang.IllegalStateException: Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path $

I tried to use Spoonacular API in Android using Jetpack Compose and Kotlin
but I got an error
BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path $
and I can't figure out how to solve this problem
Here is my JSON Format
{
"results": [
{
"vegetarian": true,
"vegan": true,
"glutenFree": true,
"dairyFree": true,
"veryHealthy": false,
"cheap": false,
"veryPopular": false,
"sustainable": false,
"lowFodmap": false,
"weightWatcherSmartPoints": 0,
"gaps": "GAPS_FULL",
"preparationMinutes": -1,
"cookingMinutes": -1,
"aggregateLikes": 1,
"healthScore": 51,
"creditsText": "Foodista.com – The Cooking Encyclopedia Everyone Can Edit",
"license": "CC BY 3.0",
"sourceName": "Foodista",
"pricePerServing": 81.7,
"extendedIngredients": [
{
"id": 11080,
"aisle": "Produce",
"image": "beets.jpg",
"consistency": "SOLID",
"name": "beet",
"nameClean": "red beet",
"original": "1 Beet, peeled",
"originalName": "Beet, peeled",
"amount": 1.0,
"unit": "",
"meta": [
"peeled"
],
"measures": {
"us": {
"amount": 1.0,
"unitShort": "",
"unitLong": ""
},
"metric": {
"amount": 1.0,
"unitShort": "",
"unitLong": ""
}
}
},
{
"id": 11124,
"aisle": "Produce",
"image": "sliced-carrot.png",
"consistency": "SOLID",
"name": "carrots",
"nameClean": "carrot",
"original": "1 pound Carrots, peeled",
"originalName": "Carrots, peeled",
"amount": 1.0,
"unit": "pound",
"meta": [
"peeled"
],
"measures": {
"us": {
"amount": 1.0,
"unitShort": "lb",
"unitLong": "pound"
},
"metric": {
"amount": 453.592,
"unitShort": "g",
"unitLong": "grams"
}
}
},
{
"id": 9200,
"aisle": "Produce",
"image": "orange.png",
"consistency": "SOLID",
"name": "oranges",
"nameClean": "orange",
"original": "2 pounds Oranges, peeled",
"originalName": "Oranges, peeled",
"amount": 2.0,
"unit": "pounds",
"meta": [
"peeled"
],
"measures": {
"us": {
"amount": 2.0,
"unitShort": "lb",
"unitLong": "pounds"
},
"metric": {
"amount": 907.185,
"unitShort": "g",
"unitLong": "grams"
}
}
}
],
"id": 1095729,
"title": "Immunity Booster Beet, Carrot & Orange Juice",
"readyInMinutes": 10,
"servings": 4,
"sourceUrl": "https://www.foodista.com/recipe/HHM34WCD/immune-booster-beet-carrot-orange-juice",
"image": "https://spoonacular.com/recipeImages/1095729-312x231.jpg",
"imageType": "jpg",
"summary": "Need a <b>gluten free, dairy free, paleolithic, and lacto ovo vegetarian beverage</b>? Immunity Booster Beet, Carrot & Orange Juice could be an outstanding recipe to try. This recipe makes 4 servings with <b>162 calories</b>, <b>4g of protein</b>, and <b>1g of fat</b> each. For <b>82 cents per serving</b>, this recipe <b>covers 18%</b> of your daily requirements of vitamins and minerals. This recipe from Foodista has 1 fans. If you have beet, carrots, oranges, and a few other ingredients on hand, you can make it. From preparation to the plate, this recipe takes roughly <b>10 minutes</b>. Overall, this recipe earns an <b>amazing spoonacular score of 89%</b>. If you like this recipe, you might also like recipes such as Goji-Orange-Turmeric Smoothie (“The Immunity Booster”), Rejuvenating Root Juice | Carrot, Beet, Blood Orange, Ginger, Turmeric Juice, and Rejuvenating Root Juice | Carrot, Beet, Blood Orange, Ginger, Turmeric Juice.",
"cuisines": [
],
"dishTypes": [
"beverage",
"drink"
],
"diets": [
"gluten free",
"dairy free",
"paleolithic",
"lacto ovo vegetarian",
"primal",
"whole 30",
"vegan"
],
"occasions": [
],
"analyzedInstructions": [
{
"name": "",
"steps": [
{
"number": 1,
"step": "Roughly chop the beet, carrots and oranges. When peeling and chopping the beet, use gloves and apron to avoid staining your hands and clothes.Throw them in a juicer and in about 2 minutes you will end up with this delicious healthy juice.",
"ingredients": [
{
"id": 11124,
"name": "carrot",
"localizedName": "carrot",
"image": "sliced-carrot.png"
},
{
"id": 9200,
"name": "orange",
"localizedName": "orange",
"image": "orange.png"
},
{
"id": 1019016,
"name": "juice",
"localizedName": "juice",
"image": "apple-juice.jpg"
},
{
"id": 11080,
"name": "beet",
"localizedName": "beet",
"image": "beets.jpg"
}
],
"equipment": [
{
"id": 404683,
"name": "juicer",
"localizedName": "juicer",
"image": "juicer.jpg"
}
],
"length": {
"number": 2,
"unit": "minutes"
}
}
]
}
],
"spoonacularSourceUrl": "https://spoonacular.com/immunity-booster-beet-carrot-orange-juice-1095729",
"usedIngredientCount": 0,
"missedIngredientCount": 3,
"missedIngredients": [
{
"id": 11080,
"amount": 1.0,
"unit": "",
"unitLong": "",
"unitShort": "",
"aisle": "Produce",
"name": "beet",
"original": "1 Beet, peeled",
"originalName": "Beet, peeled",
"meta": [
"peeled"
],
"image": "https://spoonacular.com/cdn/ingredients_100x100/beets.jpg"
},
{
"id": 11124,
"amount": 1.0,
"unit": "pound",
"unitLong": "pound",
"unitShort": "lb",
"aisle": "Produce",
"name": "carrots",
"original": "1 pound Carrots, peeled",
"originalName": "Carrots, peeled",
"meta": [
"peeled"
],
"image": "https://spoonacular.com/cdn/ingredients_100x100/sliced-carrot.png"
},
{
"id": 9200,
"amount": 2.0,
"unit": "pounds",
"unitLong": "pounds",
"unitShort": "lb",
"aisle": "Produce",
"name": "oranges",
"original": "2 pounds Oranges, peeled",
"originalName": "Oranges, peeled",
"meta": [
"peeled"
],
"image": "https://spoonacular.com/cdn/ingredients_100x100/orange.png"
}
],
"likes": 0,
"usedIngredients": [
],
"unusedIngredients": [
]
}
],
"offset": 0,
"number": 1,
"totalResults": 40
}
Model
data class ResultX(
#SerializedName("aggregateLikes")
val aggregateLikes: Int,
#SerializedName("cheap")
val cheap: Boolean,
#SerializedName("dairyFree")
val dairyFree: Boolean,
#SerializedName("extendedIngredients")
val extendedIngredients: List<ExtendedIngredient>,
#SerializedName("glutenFree")
val glutenFree: Boolean,
#SerializedName("id")
val id: Int,
#SerializedName("image")
val image: String,
#SerializedName("likes")
val likes: Int,
#SerializedName("readyInMinutes")
val readyInMinutes: Int,
#SerializedName("servings")
val servings: Int,
#SerializedName("sourceName")
val sourceName: String,
#SerializedName("sourceUrl")
val sourceUrl: String,
#SerializedName("summary")
val summary: String,
#SerializedName("title")
val title: String,
#SerializedName("vegan")
val vegan: Boolean,
#SerializedName("vegetarian")
val vegetarian: Boolean,
#SerializedName("veryHealthy")
val veryHealthy: Boolean
)
data class ExtendedIngredient(
#SerializedName("amount")
val amount: Double,
#SerializedName("consistency")
val consistency: String,
#SerializedName("image")
val image: String,
#SerializedName("name")
val name: String,
#SerializedName("original")
val original: String,
#SerializedName("unit")
val unit: String
)
API INTERFACE
#GET("/recipes/complexSearch")
suspend fun getRecipes(
#QueryMap queries: Map<String, String>
): List<ResultX>
RESOURCE CLASS AND API REPOSITORY IMPLEMENTATION
sealed class Resource<T>(val data: T? = null, val message: String? = null){
class Success<T>(data: T): Resource<T>(data)
class Error<T>(message: String?, data: T? = null): Resource<T>(data, message)
class Loading<T>(data: T? = null): Resource<T>(data)
}
interface FoodApiRepository {
fun getRecipes(queries: Map<String, String>): Flow<Resource<List<ResultX>>>
}
class FoodApiRepositoryImpl #Inject constructor(
private val foodApi: FoodApi
): FoodApiRepository {
override fun getRecipes(queries: Map<String, String>): Flow<Resource<List<ResultX>>> {
return flow {
try {
emit(Resource.Loading())
val result = foodApi.getRecipes(queries = queries)
emit(
Resource.Success(
data = result
)
)
}catch (e: HttpException){
emit(Resource.Error(e.localizedMessage ?: "An expected error occurred"))
}catch (e: IOException){
emit(Resource.Error("Couldn't reach server. Check your internet connection"))
}
}
}
}
FOOD LIST STATE CLASS AND HOME VIEW MODEL
data class FoodListState(
val isLoading: Boolean = false,
val recipes: List<ResultX> = emptyList(),
val error: String = ""
)
#HiltViewModel
class HomeViewModel #Inject constructor(
private val foodApiRepository: FoodApiRepository
): ViewModel(){
private val _state = mutableStateOf(FoodListState())
val state: State<FoodListState> = _state
init {
getRecipes(applyQueries())
}
private fun getRecipes(queries: Map<String, String>) {
foodApiRepository.getRecipes(queries = queries).onEach { result ->
when(result) {
is Resource.Success -> {
_state.value = FoodListState(recipes = result.data ?: emptyList())
}
is Resource.Error -> {
_state.value =
FoodListState(
error = result.message ?: "An un expected error occurred"
)
Log.d("TAG", "getFoodRecipes: ERROR")
}
is Resource.Loading -> {
_state.value = FoodListState(isLoading = true)
}
}
}.launchIn(viewModelScope)
}
private fun applyQueries(): HashMap<String, String> {
val queries: HashMap<String, String> = HashMap()
queries["number"] = "50"
queries["apiKey"] = API_KEY
queries["type"] = "snack"
queries["diet"] = "vegan"
queries["addRecipeInformation"] = "true"
queries["fillIngredients"] = "true"
Log.d("TAG", "applyQueries: $queries")
return queries
}
}
HOME SCREEN
#Composable
fun HomeScreen(
navController: NavController,
homeViewModel: HomeViewModel = hiltViewModel()
) {
val state = homeViewModel.state.value
Box(modifier = Modifier.fillMaxSize()){
LazyColumn(modifier = Modifier.fillMaxSize()) {
items(state.recipes) { recipe ->
Text(
text = recipe.title,
style = MaterialTheme.typography.subtitle1,
overflow = TextOverflow.Ellipsis,
modifier = Modifier
.fillMaxWidth()
.padding(20.dp)
)
}
}
if (state.error.isNotBlank()){
Text(
text = state.error,
color = MaterialTheme.colors.error,
textAlign = TextAlign.Center,
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 20.dp)
.align(
Alignment.Center
)
)
}
if (state.isLoading){
CircularProgressIndicator(modifier = Modifier.align(Alignment.Center))
}
}
}
THANK YOU
You're parsing it wrong. Your Retrofit function says it returns a List. That's not what the JSON being returned is. It's returning a JSON object, not a JSON Array. You need another class ResultWrapper which has a a list of ResultX in it named result, and have the Retrofit API return that.

Retrofit Kotlin RecyclerView Problem...I can show only 1 element...Json GSON list has 1 size [duplicate]

This question already has answers here:
Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2
(2 answers)
Closed 12 months ago.
I cant generate a true code for showing all the element in recyclerView...or i can only show 1 element when i use this code on RecyclerAdapter - holder.tvValueName.text = currentItem.AMD.Name
but when i want add all elements whit this code - holder.tvValueName.text = currentItem.currencyModel.Name - it didnt work...
I already tried change the types of some classes like a val valute: Valute -to- val valute:List<Valute> or val currencyModel: CurrencyModel -to- val currencyModel: List<CurrencyModel>
and then get values with method holder.tvValueName.text = currentItem.currencyModel.get(position).Name - but i get error with ARRAY...
If anyone has any ideas please help, thanks in advance
interface ApiInterface {
#GET("daily_json.js")
fun getValuteData() : Call<Main>
companion object {
var BASE_URL = "https://www.cbr-xml-daily.ru/"
fun create() : ApiInterface {
val retrofit = Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create())
.baseUrl(BASE_URL)
.build()
return retrofit.create(ApiInterface::class.java)
}
}
}
class RecyclerAdapter(val context: Context) : RecyclerView.Adapter<RecyclerAdapter.MyViewHolder>() {
var valuteItemList : MutableList<Valute> = mutableListOf()
private var changedData: MutableList<Valute> = mutableListOf()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.recyclerview_adapter,parent,false)
return MyViewHolder(view)
}
override fun getItemCount(): Int {
return changedData.size
}
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
val currentItem = changedData[position]
holder.tvValueName.text = currentItem.AMD.Name
holder.tvValueName.text = currentItem.currencyModel.Name
}
#SuppressLint("NotifyDataSetChanged")
fun setValuteListItems(valuteList: MutableList<Valute>){
valuteItemList.clear()
valuteItemList.addAll(valuteList)
changedData.addAll(valuteItemList)
notifyDataSetChanged()
}
class MyViewHolder(itemView: View?) : RecyclerView.ViewHolder(itemView!!) {
val tvValueName: TextView = itemView!!.findViewById(R.id.title)
val tvValuteValue: TextView = itemView!!.findViewById(R.id.valute_value)
val tvValuteCharCode: TextView = itemView!!.findViewById(R.id.chare_code)
val image: ImageView = itemView!!.findViewById(R.id.image)
}
}
class MainActivity : AppCompatActivity() {
lateinit var recyclerView: RecyclerView
lateinit var recyclerAdapter: RecyclerAdapter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
recyclerView = findViewById(R.id.recyclerview)
recyclerAdapter = RecyclerAdapter(this)
recyclerView.layoutManager = LinearLayoutManager(this)
recyclerView.adapter = recyclerAdapter
val apiInterface = ApiInterface.create().getValuteData()
apiInterface.enqueue( object : Callback<Main> {
override fun onResponse(call: Call<Main>?, response: Response<Main>?) {
Log.d("MyTag","Success ")
if(response!!.body() != null)
//recyclerAdapter.setValuteListItems(response.body()!!.Valute as MutableList<Valute>)
recyclerAdapter.setValuteListItems(mutableListOf(response.body()!!.Valute))
Log.d("MyTag","Success "+response.body().toString())
}
override fun onFailure(call: Call<Main>?, t: Throwable?) {
Log.d("MyTag", "Failure "+t.toString())
}
})
}
}
Whole JSON Model
data class Main(
val Date: String,
val PreviousDate: String,
val PreviousURL: String,
val Timestamp: String,
val Valute: Valute
)
data class CurrencyModel(
val CharCode: String,
val ID: String,
val Name: String,
val Nominal: Int,
val NumCode: String,
val Previous: Double,
val Value: Double
)
data class Valute(
val currencyModel: CurrencyModel,
val AMD: CurrencyModel,
val AUD: CurrencyModel,
val AZN: CurrencyModel,
val BGN: CurrencyModel,
val BRL: CurrencyModel,
val BYN: CurrencyModel,
val CAD: CurrencyModel,
val CHF: CurrencyModel,
val CNY: CurrencyModel,
val CZK: CurrencyModel,
val DKK: CurrencyModel,
val EUR: CurrencyModel,
val GBP: CurrencyModel,
val HKD: CurrencyModel,
val HUF: CurrencyModel,
val INR: CurrencyModel,
val JPY: CurrencyModel,
val KGS: CurrencyModel,
val KRW: CurrencyModel,
val KZT: CurrencyModel,
val MDL: CurrencyModel,
val NOK: CurrencyModel,
val PLN: CurrencyModel,
val RON: CurrencyModel,
val SEK: CurrencyModel,
val SGD: CurrencyModel,
val TJS: CurrencyModel,
val TMT: CurrencyModel,
val TRY: CurrencyModel,
val UAH: CurrencyModel,
val USD: CurrencyModel,
val UZS: CurrencyModel,
val XDR: CurrencyModel,
val ZAR: CurrencyModel
)
JSON
{
"Date": "2022-03-02T11:30:00+03:00",
"PreviousDate": "2022-03-01T11:30:00+03:00",
"PreviousURL": "\/\/www.cbr-xml-daily.ru\/archive\/2022\/03\/01\/daily_json.js",
"Timestamp": "2022-03-01T18:00:00+03:00",
"Valute": {
"AUD": {
"ID": "R01010",
"NumCode": "036",
"CharCode": "AUD",
"Nominal": 1,
"Name": "Австралийский доллар",
"Value": 66.7817,
"Previous": 67.3624
},
"AZN": {
"ID": "R01020A",
"NumCode": "944",
"CharCode": "AZN",
"Nominal": 1,
"Name": "Азербайджанский манат",
"Value": 53.9998,
"Previous": 55.067
},
"GBP": {
"ID": "R01035",
"NumCode": "826",
"CharCode": "GBP",
"Nominal": 1,
"Name": "Фунт стерлингов Соединенного королевства",
"Value": 123.1411,
"Previous": 125.0415
},
"AMD": {
"ID": "R01060",
"NumCode": "051",
"CharCode": "AMD",
"Nominal": 100,
"Name": "Армянских драмов",
"Value": 18.8196,
"Previous": 19.524
},
"BYN": {
"ID": "R01090B",
"NumCode": "933",
"CharCode": "BYN",
"Nominal": 1,
"Name": "Белорусский рубль",
"Value": 29.4765,
"Previous": 33.9264
},
"BGN": {
"ID": "R01100",
"NumCode": "975",
"CharCode": "BGN",
"Nominal": 1,
"Name": "Болгарский лев",
"Value": 52.5944,
"Previous": 53.4592
},
"BRL": {
"ID": "R01115",
"NumCode": "986",
"CharCode": "BRL",
"Nominal": 1,
"Name": "Бразильский реал",
"Value": 17.7795,
"Previous": 18.1182
},
"HUF": {
"ID": "R01135",
"NumCode": "348",
"CharCode": "HUF",
"Nominal": 100,
"Name": "Венгерских форинтов",
"Value": 27.7437,
"Previous": 28.0932
},
"HKD": {
"ID": "R01200",
"NumCode": "344",
"CharCode": "HKD",
"Nominal": 1,
"Name": "Гонконгский доллар",
"Value": 11.7413,
"Previous": 11.9737
},
"DKK": {
"ID": "R01215",
"NumCode": "208",
"CharCode": "DKK",
"Nominal": 1,
"Name": "Датская крона",
"Value": 13.8309,
"Previous": 14.0504
},
"USD": {
"ID": "R01235",
"NumCode": "840",
"CharCode": "USD",
"Nominal": 1,
"Name": "Доллар США",
"Value": 91.7457,
"Previous": 93.5589
},
"EUR": {
"ID": "R01239",
"NumCode": "978",
"CharCode": "EUR",
"Nominal": 1,
"Name": "Евро",
"Value": 102.9112,
"Previous": 104.4772
},
"INR": {
"ID": "R01270",
"NumCode": "356",
"CharCode": "INR",
"Nominal": 10,
"Name": "Индийских рупий",
"Value": 12.1817,
"Previous": 12.3927
},
"KZT": {
"ID": "R01335",
"NumCode": "398",
"CharCode": "KZT",
"Nominal": 100,
"Name": "Казахстанских тенге",
"Value": 18.6621,
"Previous": 18.8393
},
"CAD": {
"ID": "R01350",
"NumCode": "124",
"CharCode": "CAD",
"Nominal": 1,
"Name": "Канадский доллар",
"Value": 72.4346,
"Previous": 73.2646
},
"KGS": {
"ID": "R01370",
"NumCode": "417",
"CharCode": "KGS",
"Nominal": 10,
"Name": "Киргизских сомов",
"Value": 10.7936,
"Previous": 11.0069
},
"CNY": {
"ID": "R01375",
"NumCode": "156",
"CharCode": "CNY",
"Nominal": 1,
"Name": "Китайский юань",
"Value": 14.534,
"Previous": 14.8243
},
"MDL": {
"ID": "R01500",
"NumCode": "498",
"CharCode": "MDL",
"Nominal": 10,
"Name": "Молдавских леев",
"Value": 49.8618,
"Previous": 50.8472
},
"NOK": {
"ID": "R01535",
"NumCode": "578",
"CharCode": "NOK",
"Nominal": 1,
"Name": "Норвежская крона",
"Value": 10.4292,
"Previous": 10.4927
},
"PLN": {
"ID": "R01565",
"NumCode": "985",
"CharCode": "PLN",
"Nominal": 1,
"Name": "Польский злотый",
"Value": 21.9288,
"Previous": 22.2151
},
"RON": {
"ID": "R01585F",
"NumCode": "946",
"CharCode": "RON",
"Nominal": 1,
"Name": "Румынский лей",
"Value": 20.7899,
"Previous": 21.1342
},
"XDR": {
"ID": "R01589",
"NumCode": "960",
"CharCode": "XDR",
"Nominal": 1,
"Name": "СДР (специальные права заимствования)",
"Value": 127.9724,
"Previous": 130.4436
},
"SGD": {
"ID": "R01625",
"NumCode": "702",
"CharCode": "SGD",
"Nominal": 1,
"Name": "Сингапурский доллар",
"Value": 67.764,
"Previous": 68.8743
},
"TJS": {
"ID": "R01670",
"NumCode": "972",
"CharCode": "TJS",
"Nominal": 10,
"Name": "Таджикских сомони",
"Value": 81.2988,
"Previous": 82.8688
},
"TRY": {
"ID": "R01700J",
"NumCode": "949",
"CharCode": "TRY",
"Nominal": 10,
"Name": "Турецких лир",
"Value": 66.1464,
"Previous": 67.7806
},
"TMT": {
"ID": "R01710A",
"NumCode": "934",
"CharCode": "TMT",
"Nominal": 1,
"Name": "Новый туркменский манат",
"Value": 26.2506,
"Previous": 26.7694
},
"UZS": {
"ID": "R01717",
"NumCode": "860",
"CharCode": "UZS",
"Nominal": 10000,
"Name": "Узбекских сумов",
"Value": 84.384,
"Previous": 86.3067
},
"UAH": {
"ID": "R01720",
"NumCode": "980",
"CharCode": "UAH",
"Nominal": 10,
"Name": "Украинских гривен",
"Value": 30.4044,
"Previous": 31.0053
},
"CZK": {
"ID": "R01760",
"NumCode": "203",
"CharCode": "CZK",
"Nominal": 10,
"Name": "Чешских крон",
"Value": 41.0266,
"Previous": 41.8215
},
"SEK": {
"ID": "R01770",
"NumCode": "752",
"CharCode": "SEK",
"Nominal": 10,
"Name": "Шведских крон",
"Value": 96.7925,
"Previous": 98.1669
},
"CHF": {
"ID": "R01775",
"NumCode": "756",
"CharCode": "CHF",
"Nominal": 1,
"Name": "Швейцарский франк",
"Value": 100.2028,
"Previous": 101.0683
},
"ZAR": {
"ID": "R01810",
"NumCode": "710",
"CharCode": "ZAR",
"Nominal": 10,
"Name": "Южноафриканских рэндов",
"Value": 59.9571,
"Previous": 60.8375
},
"KRW": {
"ID": "R01815",
"NumCode": "410",
"CharCode": "KRW",
"Nominal": 1000,
"Name": "Вон Республики Корея",
"Value": 76.5619,
"Previous": 77.7626
},
"JPY": {
"ID": "R01820",
"NumCode": "392",
"CharCode": "JPY",
"Nominal": 100,
"Name": "Японских иен",
"Value": 79.7962,
"Previous": 80.9718
}
}
}
In your model change
val Valute: Valute
to
val Valute = ArrayList()
and change your response json from
"Valute": {
"AUD": {
to
"Valute": [
"AUD": {
By changing this you can get the Valute as Arraylist and then you can load the data in adapter

Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2. How to solve it?

I'm trying to retrieve data and display them in a recycler view.
I'm working with retrofit, making a get request..
Everything is fine, except: it won't display data in the recycler because it says:
"Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2".
I also used the kotlin data class file from JSON plugin to generate data classes from the response.
I don't know what to do, I'm stuck..
Here are my classes:
ApiClient.kt
object ApiClient {
private const val BASE_URL: String = "https://dev.fastbeach.it/api/"
private val gson : Gson by lazy {
GsonBuilder().setLenient().create()
}
private val httpClient : OkHttpClient by lazy {
OkHttpClient.Builder().build()
}
private val retrofit : Retrofit by lazy {
Retrofit.Builder()
.baseUrl(BASE_URL)
.client(httpClient)
.addConverterFactory(GsonConverterFactory.create(gson))
.build()
}
val apiService : ApiService by lazy{
retrofit.create(ApiService::class.java)
}
ApiService.kt
interface ApiService {
#GET("tenant/searchAllWithPagesAndFilters")
fun getUsers(
#Query("reservationEnabled") reservationEnabled:Boolean,
#Query("page") page:Int,
#Query("size") size:Int,
#Query("sort") sort:String,
#Query("direction") direction:String
): Call<MutableList<User>>
UserRepository.kt
object UserRepository {
fun getMutableLiveData(context: Context) : MutableLiveData<ArrayList<User>>{
val mutableLiveData = MutableLiveData<ArrayList<User>>()
context.showProgressBar()
ApiClient.apiService.getUsers(true,0,5,"order","ASC").enqueue(object : Callback<MutableList<User>> {
override fun onFailure(call: Call<MutableList<User>>, t: Throwable) {
hideProgressBar()
Log.e("error", t.localizedMessage)
}
override fun onResponse(
call: Call<MutableList<User>>,
response: Response<MutableList<User>>
) {
hideProgressBar()
val usersResponse = response.body()
usersResponse?.let { mutableLiveData.value = it as ArrayList<User> }
}
})
return mutableLiveData
}
UserViewModel.kt
class UserViewModel(private val context: Context) : ViewModel() {
private var listData = MutableLiveData<ArrayList<User>>()
init{
val userRepository : UserRepository by lazy {
UserRepository
}
if(context.isInternetAvailable()) {
listData = userRepository.getMutableLiveData(context)
}
}
fun getData() : MutableLiveData<ArrayList<User>>{
return listData
}
MainActivity.kt
class MainActivity : AppCompatActivity() {
private lateinit var listUsers: MutableList<User>
private lateinit var adapter: UsersAdapter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
recycler_main.layoutManager = LinearLayoutManager(this#MainActivity)
listUsers = mutableListOf<User>()
adapter = UsersAdapter(this,
listUsers
)
recycler_main.adapter = adapter
val userViewModel = ViewModelProviders.of(this,UserViewModelFactory(this)).get(UserViewModel::class.java)
userViewModel.getData().observe(this,object:Observer<ArrayList<User>>{
override fun onChanged(t: ArrayList<User>?) {
listUsers.clear()
t?.let { listUsers.addAll(it) }
adapter.notifyDataSetChanged()
}
})
}
API response from POSTMAN
{
"content": [
{
"id": "609d2d79be5f8e42d9c13e41",
"name": "bagno-sirena-posillipo",
"title": "Bagno Sirena Posillipo",
"tenantName": "Bagno Sirena",
"tenantCode": "BSI",
"description": "E' uno dei siti balneari più antichi, inserito in un posto incantevole a ridosso del Palazzo Donn'Anna, in una piccola insenatura riparata e quindi usufruibile in tutti i mesi dell'anno per chi vuole in piena città trascorrere qualche ora di relax respirando aria di mare e conservare l'abbronzatura estiva.\nI gestori si stanno impegnando per migliorare i servizi della location.\nVorremmo condividere con tutti gli amanti del mare e della costa di Posillipo questa meraviglia che abbiamo.\nVeniteci a trovare e avrete modo di constatare questa bellezza.",
"confirmBookingsRequired": false,
"paymentRequired": true,
"fee": 1.0,
"foodFee": 0.5,
"feePercentage": 0.02,
"foodFeePercentage": 0.02,
"percentage": true,
"signInSignOnEnabled": true,
"qrCodeValidation": true,
"tenantImage": {},
"tenantOtherImage": [],
"type": "Beach",
"enabledServices": [],
"master": false,
"comune": "Napoli",
"comuneId": "063049",
"address": {
"address": "Via Posillipo, 357",
"city": "Napoli",
"province": "NA",
"country": "Italia",
"postalNumber": "80123",
"phoneNumber": "081 769 2885",
"web": "https://www.facebook.com/bagnosirenanapoli/",
"email": "development#synclab.it"
},
"reservationEnabled": true,
"foodEnabled": true,
"reservationWithoutMapButWithCart": false,
"criteriaNumPlaces": {},
"supportedServices": [
{
"id": "5f04a23f968f9926b4b76746",
"name": "Lettini",
"description": "Lettini",
"supported": true,
"tenantTypes": []
},
{
"id": "5f04a240968f9926b4b76747",
"name": "Ombrelloni",
"description": "Ombrelloni",
"supported": true,
"tenantTypes": []
},
{
"id": "5f04a240968f9926b4b76748",
"name": "Sdraio",
"description": "Sdraio",
"supported": false,
"tenantTypes": []
},
{
"id": "5f04a240968f9926b4b76749",
"name": "Parcheggio",
"description": "Parcheggio",
"supported": false,
"tenantTypes": []
},
{
"id": "5f04a240968f9926b4b7674a",
"name": "Lettoni",
"description": "Lettoni",
"supported": false,
"tenantTypes": []
},
{
"id": "5f04a240968f9926b4b7674b",
"name": "Accessibilita",
"description": "Accesso disabili\n",
"supported": false,
"tenantTypes": []
},
{
"id": "5f04a240968f9926b4b7674c",
"name": "Area_baby",
"description": "Area baby",
"supported": false,
"tenantTypes": []
},
{
"id": "5f04a240968f9926b4b7674d",
"name": "Ristorante",
"description": "Ristorante",
"supported": true,
"tenantTypes": []
},
{
"id": "5f04a240968f9926b4b7674e",
"name": "Bar",
"description": "Bar",
"supported": false,
"tenantTypes": []
},
{
"id": "5f04a240968f9926b4b7674f",
"name": "Alcolici",
"description": "Alcolici",
"supported": false,
"tenantTypes": []
},
{
"id": "5f04a240968f9926b4b76750",
"name": "Gazebo",
"description": "Gazebo",
"supported": false,
"tenantTypes": []
},
{
"id": "5f04a240968f9926b4b76751",
"name": "Pagoda",
"description": "Pagoda",
"supported": false,
"tenantTypes": []
},
{
"id": "5f04a240968f9926b4b76752",
"name": "Wc",
"description": "Wc",
"supported": true,
"tenantTypes": []
},
{
"id": "60c72a1709e2081fa9b6d422",
"name": "Wi-fi",
"description": "Wi-fi",
"supported": false,
"tenantTypes": []
},
{
"id": "60c72a2509e2081fa9b6d423",
"name": "Accesso_animali",
"description": "Animali",
"supported": false,
"tenantTypes": []
},
{
"id": "60c72a2709e2081fa9b6d424",
"name": "Animazione",
"description": "Animazione",
"supported": false,
"tenantTypes": []
},
{
"id": "60c72a2a09e2081fa9b6d425",
"name": "Cabine",
"description": "Cabine",
"supported": false,
"tenantTypes": []
},
{
"id": "60c72a4109e2081fa9b6d426",
"name": "Piscina",
"description": "Piscina",
"supported": false,
"tenantTypes": []
},
{
"id": "60ec61341dbc2d4ed0d130ff",
"name": "Sedia_regista",
"description": "Sedia regista",
"supported": false,
"searchable": true,
"tenantTypes": []
}
],
"types": [
{
"typeId": "60c73af609e2081fa9b6d42a",
"name": "Sassi",
"description": "Sassi",
"supported": false,
"tenantTypes": []
},
{
"typeId": "60c73af609e2081fa9b6d42b",
"name": "Erba_sintetica",
"description": "Erba sintetica",
"supported": false,
"tenantTypes": []
},
{
"typeId": "60c73af609e2081fa9b6d42c",
"name": "Molo",
"description": "Molo",
"supported": false,
"tenantTypes": []
},
{
"typeId": "60ccb0874107e97fccaac087",
"name": "Spiaggia",
"description": "Spiaggia",
"supported": true,
"tenantTypes": []
},
{
"typeId": "60ccb0874107e97fccaac088",
"name": "Erba_naturale",
"description": "Erba naturale",
"supported": false,
"tenantTypes": []
},
{
"typeId": "60ccb0874107e97fccaac089",
"name": "Ciottoli",
"description": "Ciottoli",
"supported": false,
"tenantTypes": []
}
],
"targets": [
{
"id": "60c73af609e2081fa9b6d42d",
"name": "Famiglie",
"description": "Famiglie",
"supported": true,
"tenantTypes": []
},
{
"id": "60c73af609e2081fa9b6d42e",
"name": "Coppie",
"description": "Coppie",
"supported": true,
"tenantTypes": []
},
{
"id": "60c73af609e2081fa9b6d42f",
"name": "Ragazzi",
"description": "Ragazzi",
"supported": false,
"tenantTypes": []
}
],
"visible": true,
"maxNumBookingGuests": 0,
"numBookablePlaces": 0,
"maxPlacesPerBooking": 0,
"withoutLayout": false,
"lastMinute": true,
"upfront": false,
"latitude": 40.8197859,
"longitude": 14.2113269,
"order": 1,
"bookingUserDetailActive": false
}
],
"pageable": {
"sort": {
"sorted": true,
"unsorted": false,
"empty": false
},
"pageNumber": 0,
"pageSize": 1,
"offset": 0,
"paged": true,
"unpaged": false
},
"last": true,
"totalElements": 1,
"totalPages": 1,
"sort": {
"sorted": true,
"unsorted": false,
"empty": false
},
"first": true,
"number": 0,
"numberOfElements": 1,
"size": 1,
"empty": false
Data classes generated through the plugin. (I'll just paste this one)
data class User(
#SerializedName("content")
val content: Content? = null,
#SerializedName("empty")
val empty: Boolean? = null,
#SerializedName("first")
val first: Boolean? = null,
#SerializedName("last")
val last: Boolean? = null,
#SerializedName("number")
val number: Int? = null,
#SerializedName("numberOfElements")
val numberOfElements: Int? = null,
#SerializedName("size")
val size: Int? = null,
#SerializedName("totalElements")
val totalElements: Int? = null,
#SerializedName("totalPages")
val totalPages: Int? = null
) : Serializable
You are expecting a type of data that is not provided by the server. Actually, your endpoint returns you a json object while you expect a list of users.
you need to create another data class that holds a list of users.
If you are lost in creating data classes, i encourage you to use JsonToKotlin Android Studio extension to implement them easily.

Moshi Expected BEGIN_OBJECT but was BEGIN_ARRAY

I am developing an Android application.
I get the following error when receiving information from the server:
Expected BEGIN_OBJECT but was BEGIN_ARRAY at path $.data
I will attach the following files to the attachment for more details.
Server Response:
{
"status": "Success",
"data": [
{
"reserve_type": "history",
"reserve_id": 163,
"payment_status": true,
"ship": {
"code": "#1",
"photo": "#",
"name": "",
"rate": null
},
"factor_detail": {
"trip": "526.00",
"transit": "356.40",
"extra_hour": {
"price": "1052.00",
"time": "2:0"
},
"items": [],
"reserve_dates": {
"start_date": "27 of July 01:30 PM",
"end_date": "27 of July 04:30 PM"
},
"product": {
"code": "#1",
"name": "",
"photo": "#"
},
"discount": "0.00",
"tax": "348.19",
"finalReservePriceWithoutPercent": "2282.59",
"finall_reserve_price": "2282.59"
},
"comment": null,
"scores": {
"items": [],
"final_rate": null
}
},
{
"reserve_type": "on_going",
"reserve_id": 168,
"payment_status": false,
"ship": {
"code": "#28",
"photo": "#",
"name": "",
"rate": null
},
"factor_detail": {
"trip": "3297.50",
"transit": "1087.50",
"extra_hour": {
"price": "17147.00",
"time": "13:0"
},
"items": [],
"reserve_dates": {
"start_date": "29 of July 07:30 AM",
"end_date": "29 of July 11:00 PM"
},
"product": {
"code": "#28",
"name": "",
"photo": "#"
},
"discount": "0.00",
"tax": "3875.76",
"finalReservePriceWithoutPercent": "25407.76",
"finall_reserve_price": "25407.76"
},
"cancel": false,
"nearest": true
}
],
"code": 200
}
ResponseBody.kt:
class ResponseBody<T>(
val status: String,
val data: T,
val code: Int
)
ResReserve.kt:
data class ResReserves(
val reserves: List<ApiReserve>
)
ApiReserve.kt:
#SuppressLint("ParcelCreator")
#Parcelize
data class ApiReserve(
#Json(name = "reserve_type")
val reserveType: String,
#Json(name = "reserve_id")
val reserveId: Int,
#Json(name = "payment_status")
val paymentStatus: Boolean,
#Json(name = "ship")
val ship: ApiShip,
#Json(name = "factor_detail")
val factorDetail: ApiFactorDetail,
#Json(name = "comment")
val comments: #RawValue Any? = null,
#Json(name = "scores")
val scores: ApiScores?,
#Json(name = "scores")
val cancel: Boolean?,
#Json(name = "nearest")
val nearest: Boolean?
) : Parcelable
MyApiInterface:
interface ReservesApi {
#GET("#")
suspend fun getReserves(
#Query("page[number]") pageNumber: Int? = null,
#Query("page[limit]") pageLimit: Int? = null
): ResponseBody<ResReserves>
}
Please guide me so that I can fix this problem
Thank you for your attention dear friends

Retrofit Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path $ in onActivityResult

So in my app a user can take a picture of their meal and through the use of Tensorflow's image classification, it will classify what the meal is in onActivityResult. Then, using Edamam Recipe Search API, it will return a recipe for that meal to the user.
When I run my app, everything is working fine and nothing is crashing, however when I use Retrofit Callback, the onFailure method is called and I get this error:
Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path $
This is what I have in my RecipeApi interface:
#GET("search")
fun searchRecipe(
#Query("q") query: String,
#Query("app_id") app_id: String,
#Query("app_key") app_key: String,
#Query("from") from: Int,
#Query("to") to: Int
): Call<List<Recipe>>
And this is what I have in my onActivityResult in my MainActivity:
retrofit = Retrofit.Builder()
.baseUrl(Constants.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build()
jsonPlaceHolderApi = retrofit.create(RecipeApi::class.java)
call = jsonPlaceHolderApi.searchRecipe(text, Constants.API_ID, Constants.API_KEY, 0, 1)
call.enqueue(object : Callback<List<Recipe>> {
override fun onResponse(
call: Call<List<Recipe>>,
response: Response<List<Recipe>>
) {
if (!response.isSuccessful) {
println("Code: " + response.code())
return
}
recipes = response.body()!!
for (recipe: Recipe in recipes) {
var content: String = ""
content += "Yield: ${recipe.yield} + \n"
content += "Calories: ${recipe.calories} + \n"
content += "TotalWeight: ${recipe.totalWeight} + \n"
content += "Ingredients: ${recipe.ingredients} + \n"
content += "TotalNutrients: ${recipe.totalNutrients} + \n"
content += "TotalDaily: ${recipe.totalDaily} + \n\n"
println(content)
}
}
override fun onFailure(call: Call<List<Recipe>>, t: Throwable) {
println(t.message)
}
})
For jsonPlaceHolderApi, call, and recipes, I created those variables at the top of my activity:
private lateinit var jsonPlaceHolderApi: RecipeApi
private lateinit var call: Call<List<Recipe>>
private lateinit var recipes: List<Recipe>
UPDATE 1:
I have included the JSON response after using OkHttp.
{
"q": "Sandwich",
"from": 0,
"to": 1,
"more": true,
"count": 16247,
"hits": [
{
"recipe": {
"uri": "http://www.edamam.com/ontologies/edamam.owl#recipe_24b4a299a9afcd43720c49e0cd32a00b",
"label": "Cambridge Market Sandwich",
"image": "https://www.edamam.com/web-img/30b/30be47fc42c63feeeb23d465d8c7ea30.jpg",
"source": "Food52",
"url": "https://food52.com/recipes/12390-cambridge-market-sandwich",
"shareAs": "http://www.edamam.com/recipe/cambridge-market-sandwich-24b4a299a9afcd43720c49e0cd32a00b/sandwich",
"yield": 6,
"dietLabels": [],
"healthLabels": [
"Vegetarian",
"Peanut-Free",
"Tree-Nut-Free",
"Alcohol-Free",
"Immuno-Supportive"
],
"cautions": [
"Sulfites"
],
"ingredientLines": [
"1 fresh baguette, cut into sandwich parts",
"1 tablespoon good quality unsalted butter, per sandwich (so 4 tbsp if making 4 sandwiches)",
"1 apple, coxs or gala preferably (2 apples for 4 sandwiches)",
"1 slice of english blue cheese, preferably a stilton (again, or 4 slices for 4 sandwiches)"
],
"ingredients": [
{
"text": "1 fresh baguette, cut into sandwich parts",
"weight": 300,
"image": "https://www.edamam.com/food-img/470/47053c77e167539c64fef3f2a3249bb2.jpg"
},
{
"text": "1 tablespoon good quality unsalted butter, per sandwich (so 4 tbsp if making 4 sandwiches)",
"weight": 14.2,
"image": null
},
{
"text": "1 apple, coxs or gala preferably (2 apples for 4 sandwiches)",
"weight": 182,
"image": "https://www.edamam.com/food-img/42c/42c006401027d35add93113548eeaae6.jpg"
},
{
"text": "1 slice of english blue cheese, preferably a stilton (again, or 4 slices for 4 sandwiches)",
"weight": 28.35,
"image": "https://www.edamam.com/food-img/b44/b442cfc174a1a691dca574c9b7dcb47a.jpg"
}
],
"calories": 1112.5294999999999,
"totalWeight": 524.55,
"totalTime": 5,
"totalNutrients": {
"ENERC_KCAL": {
"label": "Energy",
"quantity": 1112.5294999999999,
"unit": "kcal"
},
"FAT": {
"label": "Fat",
"quantity": 27.23481,
"unit": "g"
},
"FASAT": {
"label": "Saturated",
"quantity": 14.224877500000002,
"unit": "g"
},
"FATRN": {
"label": "Trans",
"quantity": 0.48047599999999996,
"unit": "g"
},
"FAMS": {
"label": "Monounsaturated",
"quantity": 6.288785,
"unit": "g"
},
"FAPU": {
"label": "Polyunsaturated",
"quantity": 3.316726,
"unit": "g"
},
"CHOCDF": {
"label": "Carbs",
"quantity": 181.44611,
"unit": "g"
},
"FIBTG": {
"label": "Fiber",
"quantity": 10.968,
"unit": "g"
},
"SUGAR": {
"label": "Sugars",
"quantity": 32.92007,
"unit": "g"
},
"PROCNT": {
"label": "Protein",
"quantity": 38.910799999999995,
"unit": "g"
},
"CHOLE": {
"label": "Cholesterol",
"quantity": 51.792500000000004,
"unit": "mg"
},
"NA": {
"label": "Sodium",
"quantity": 2134.2729999999997,
"unit": "mg"
},
"CA": {
"label": "Calcium",
"quantity": 320.01599999999996,
"unit": "mg"
},
"MG": {
"label": "Magnesium",
"quantity": 111.9045,
"unit": "mg"
},
"K": {
"label": "Potassium",
"quantity": 621.724,
"unit": "mg"
},
"FE": {
"label": "Iron",
"quantity": 12.039125000000002,
"unit": "mg"
},
"ZN": {
"label": "Zinc",
"quantity": 3.95969,
"unit": "mg"
},
"P": {
"label": "Phosphorus",
"quantity": 448.14250000000004,
"unit": "mg"
},
"VITA_RAE": {
"label": "Vitamin A",
"quantity": 158.72099999999998,
"unit": "µg"
},
"VITC": {
"label": "Vitamin C",
"quantity": 8.372,
"unit": "mg"
},
"THIA": {
"label": "Thiamin (B1)",
"quantity": 2.1698715,
"unit": "mg"
},
"RIBF": {
"label": "Riboflavin (B2)",
"quantity": 1.441445,
"unit": "mg"
},
"NIA": {
"label": "Niacin (B3)",
"quantity": 14.910620000000002,
"unit": "mg"
},
"VITB6A": {
"label": "Vitamin B6",
"quantity": 0.44310700000000003,
"unit": "mg"
},
"FOLDFE": {
"label": "Folate equivalent (total)",
"quantity": 526.092,
"unit": "µg"
},
"FOLFD": {
"label": "Folate (food)",
"quantity": 184.09199999999998,
"unit": "µg"
},
"FOLAC": {
"label": "Folic acid",
"quantity": 201,
"unit": "µg"
},
"VITB12": {
"label": "Vitamin B12",
"quantity": 0.37001,
"unit": "µg"
},
"VITD": {
"label": "Vitamin D",
"quantity": 0.35475,
"unit": "µg"
},
"TOCPHA": {
"label": "Vitamin E",
"quantity": 1.357915,
"unit": "mg"
},
"VITK1": {
"label": "Vitamin K",
"quantity": 7.7783999999999995,
"unit": "µg"
},
"WATER": {
"label": "Water",
"quantity": 269.289915,
"unit": "g"
}
},
"totalDaily": {
"ENERC_KCAL": {
"label": "Energy",
"quantity": 55.62647499999999,
"unit": "%"
},
"FAT": {
"label": "Fat",
"quantity": 41.899707692307686,
"unit": "%"
},
"FASAT": {
"label": "Saturated",
"quantity": 71.12438750000001,
"unit": "%"
},
"CHOCDF": {
"label": "Carbs",
"quantity": 60.482036666666666,
"unit": "%"
},
"FIBTG": {
"label": "Fiber",
"quantity": 43.872,
"unit": "%"
},
"PROCNT": {
"label": "Protein",
"quantity": 77.82159999999999,
"unit": "%"
},
"CHOLE": {
"label": "Cholesterol",
"quantity": 17.264166666666668,
"unit": "%"
},
"NA": {
"label": "Sodium",
"quantity": 88.92804166666664,
"unit": "%"
},
"CA": {
"label": "Calcium",
"quantity": 32.001599999999996,
"unit": "%"
},
"MG": {
"label": "Magnesium",
"quantity": 26.643928571428575,
"unit": "%"
},
"K": {
"label": "Potassium",
"quantity": 13.228170212765958,
"unit": "%"
},
"FE": {
"label": "Iron",
"quantity": 66.88402777777779,
"unit": "%"
},
"ZN": {
"label": "Zinc",
"quantity": 35.997181818181815,
"unit": "%"
},
"P": {
"label": "Phosphorus",
"quantity": 64.02035714285715,
"unit": "%"
},
"VITA_RAE": {
"label": "Vitamin A",
"quantity": 17.635666666666662,
"unit": "%"
},
"VITC": {
"label": "Vitamin C",
"quantity": 9.302222222222223,
"unit": "%"
},
"THIA": {
"label": "Thiamin (B1)",
"quantity": 180.82262500000002,
"unit": "%"
},
"RIBF": {
"label": "Riboflavin (B2)",
"quantity": 110.88038461538463,
"unit": "%"
},
"NIA": {
"label": "Niacin (B3)",
"quantity": 93.19137500000001,
"unit": "%"
},
"VITB6A": {
"label": "Vitamin B6",
"quantity": 34.08515384615385,
"unit": "%"
},
"FOLDFE": {
"label": "Folate equivalent (total)",
"quantity": 131.523,
"unit": "%"
},
"VITB12": {
"label": "Vitamin B12",
"quantity": 15.417083333333332,
"unit": "%"
},
"VITD": {
"label": "Vitamin D",
"quantity": 2.365,
"unit": "%"
},
"TOCPHA": {
"label": "Vitamin E",
"quantity": 9.052766666666665,
"unit": "%"
},
"VITK1": {
"label": "Vitamin K",
"quantity": 6.481999999999999,
"unit": "%"
}
},
"digest": [
{
"label": "Fat",
"tag": "FAT",
"schemaOrgTag": "fatContent",
"total": 27.23481,
"hasRDI": true,
"daily": 41.899707692307686,
"unit": "g",
"sub": [
{
"label": "Saturated",
"tag": "FASAT",
"schemaOrgTag": "saturatedFatContent",
"total": 14.224877500000002,
"hasRDI": true,
"daily": 71.12438750000001,
"unit": "g"
},
{
"label": "Trans",
"tag": "FATRN",
"schemaOrgTag": "transFatContent",
"total": 0.48047599999999996,
"hasRDI": false,
"daily": 0,
"unit": "g"
},
{
"label": "Monounsaturated",
"tag": "FAMS",
"schemaOrgTag": null,
"total": 6.288785,
"hasRDI": false,
"daily": 0,
"unit": "g"
},
{
"label": "Polyunsaturated",
"tag": "FAPU",
"schemaOrgTag": null,
"total": 3.316726,
"hasRDI": false,
"daily": 0,
"unit": "g"
}
]
},
{
"label": "Carbs",
"tag": "CHOCDF",
"schemaOrgTag": "carbohydrateContent",
"total": 181.44611,
"hasRDI": true,
"daily": 60.482036666666666,
"unit": "g",
"sub": [
{
"label": "Carbs (net)",
"tag": "CHOCDF.net",
"schemaOrgTag": null,
"total": 170.47811000000002,
"hasRDI": false,
"daily": 0,
"unit": "g"
},
{
"label": "Fiber",
"tag": "FIBTG",
"schemaOrgTag": "fiberContent",
"total": 10.968,
"hasRDI": true,
"daily": 43.872,
"unit": "g"
},
{
"label": "Sugars",
"tag": "SUGAR",
"schemaOrgTag": "sugarContent",
"total": 32.92007,
"hasRDI": false,
"daily": 0,
"unit": "g"
},
{
"label": "Sugars, added",
"tag": "SUGAR.added",
"schemaOrgTag": null,
"total": 0,
"hasRDI": false,
"daily": 0,
"unit": "g"
}
]
},
{
"label": "Protein",
"tag": "PROCNT",
"schemaOrgTag": "proteinContent",
"total": 38.910799999999995,
"hasRDI": true,
"daily": 77.82159999999999,
"unit": "g"
},
{
"label": "Cholesterol",
"tag": "CHOLE",
"schemaOrgTag": "cholesterolContent",
"total": 51.792500000000004,
"hasRDI": true,
"daily": 17.264166666666668,
"unit": "mg"
},
{
"label": "Sodium",
"tag": "NA",
"schemaOrgTag": "sodiumContent",
"total": 2134.2729999999997,
"hasRDI": true,
"daily": 88.92804166666664,
"unit": "mg"
},
{
"label": "Calcium",
"tag": "CA",
"schemaOrgTag": null,
"total": 320.01599999999996,
"hasRDI": true,
"daily": 32.001599999999996,
"unit": "mg"
},
{
"label": "Magnesium",
"tag": "MG",
"schemaOrgTag": null,
"total": 111.9045,
"hasRDI": true,
"daily": 26.643928571428575,
"unit": "mg"
},
{
"label": "Potassium",
"tag": "K",
"schemaOrgTag": null,
"total": 621.724,
"hasRDI": true,
"daily": 13.228170212765958,
"unit": "mg"
},
{
"label": "Iron",
"tag": "FE",
"schemaOrgTag": null,
"total": 12.039125000000002,
"hasRDI": true,
"daily": 66.88402777777779,
"unit": "mg"
},
{
"label": "Zinc",
"tag": "ZN",
"schemaOrgTag": null,
"total": 3.95969,
"hasRDI": true,
"daily": 35.997181818181815,
"unit": "mg"
},
{
"label": "Phosphorus",
"tag": "P",
"schemaOrgTag": null,
"total": 448.14250000000004,
"hasRDI": true,
"daily": 64.02035714285715,
"unit": "mg"
},
{
"label": "Vitamin A",
"tag": "VITA_RAE",
"schemaOrgTag": null,
"total": 158.72099999999998,
"hasRDI": true,
"daily": 17.635666666666662,
"unit": "µg"
},
{
"label": "Vitamin C",
"tag": "VITC",
"schemaOrgTag": null,
"total": 8.372,
"hasRDI": true,
"daily": 9.302222222222223,
"unit": "mg"
},
{
"label": "Thiamin (B1)",
"tag": "THIA",
"schemaOrgTag": null,
"total": 2.1698715,
"hasRDI": true,
"daily": 180.82262500000002,
"unit": "mg"
},
{
"label": "Riboflavin (B2)",
"tag": "RIBF",
"schemaOrgTag": null,
"total": 1.441445,
"hasRDI": true,
"daily": 110.88038461538463,
"unit": "mg"
},
{
"label": "Niacin (B3)",
"tag": "NIA",
"schemaOrgTag": null,
"total": 14.910620000000002,
"hasRDI": true,
"daily": 93.19137500000001,
"unit": "mg"
},
{
"label": "Vitamin B6",
"tag": "VITB6A",
"schemaOrgTag": null,
"total": 0.44310700000000003,
"hasRDI": true,
"daily": 34.08515384615385,
"unit": "mg"
},
{
"label": "Folate equivalent (total)",
"tag": "FOLDFE",
"schemaOrgTag": null,
"total": 526.092,
"hasRDI": true,
"daily": 131.523,
"unit": "µg"
},
{
"label": "Folate (food)",
"tag": "FOLFD",
"schemaOrgTag": null,
"total": 184.09199999999998,
"hasRDI": false,
"daily": 0,
"unit": "µg"
},
{
"label": "Folic acid",
"tag": "FOLAC",
"schemaOrgTag": null,
"total": 201,
"hasRDI": false,
"daily": 0,
"unit": "µg"
},
{
"label": "Vitamin B12",
"tag": "VITB12",
"schemaOrgTag": null,
"total": 0.37001,
"hasRDI": true,
"daily": 15.417083333333332,
"unit": "µg"
},
{
"label": "Vitamin D",
"tag": "VITD",
"schemaOrgTag": null,
"total": 0.35475,
"hasRDI": true,
"daily": 2.365,
"unit": "µg"
},
{
"label": "Vitamin E",
"tag": "TOCPHA",
"schemaOrgTag": null,
"total": 1.357915,
"hasRDI": true,
"daily": 9.052766666666665,
"unit": "mg"
},
{
"label": "Vitamin K",
"tag": "VITK1",
"schemaOrgTag": null,
"total": 7.7783999999999995,
"hasRDI": true,
"daily": 6.481999999999999,
"unit": "µg"
},
{
"label": "Sugar alcohols",
"tag": "Sugar.alcohol",
"schemaOrgTag": null,
"total": 0,
"hasRDI": false,
"daily": 0,
"unit": "g"
},
{
"label": "Water",
"tag": "WATER",
"schemaOrgTag": null,
"total": 269.289915,
"hasRDI": false,
"daily": 0,
"unit": "g"
}
]
},
"bookmarked": false,
"bought": false
}
]
}
UPDATE 2:
I have included the Recipe class.
class Recipe {
#SerializedName(value = "yield")
var yield: Int? = null
get() = field
set(value) {
field = value
}
#SerializedName(value = "calories")
var calories: Float? = null
get() = field
set(value) {
field = value
}
#SerializedName(value = "totalWeight")
var totalWeight: Float? = null
get() = field
set(value) {
field = value
}
#SerializedName(value = "ingredients")
var ingredients: List<Ingredient>? = null
get() = field
set(value) {
field = value
}
#SerializedName(value = "totalNutrients")
var totalNutrients: Map<String, NutrientInfo>? = null
get() = field
set(value) {
field = value
}
#SerializedName(value = "totalDaily")
var totalDaily: Map<String, NutrientInfo>? = null
get() = field
set(value) {
field = value
}
}
Does anyone know how to fix this issue?
Your error tells you that it tries to make a list of something that can't be a list.
After some looking at the json I did found something that others haven't found yet.
The structure of the json is not starting as a list but as an object:
{
"q": "Sandwich",
"from": 0,
"to": 1,
"more": true,
"count": 16247,
"hits": [
// recipe is in here
]
}
This means that the Object that retrofit should be expecting is not of a type List<Recipe> but it should be an object of type RecipeResponse (defined below)
data class RecipeResponse(
#SerializedName("count")
val count: Int = 0,
#SerializedName("from")
val from: Int = 0,
#SerializedName("hits")
val hits: List<Hit>,
#SerializedName("more")
val more: Boolean = false,
#SerializedName("q")
val q: String = "",
#SerializedName("to")
val to: Int = 0
)
data class Hit(
#SerializedName("bookmarked")
val bookmarked: Boolean = false,
#SerializedName("bought")
val bought: Boolean = false,
#SerializedName("recipe")
val recipe: Recipe
)
In Hit you can use your recipe object
Don't forget to change the method in the interface to
#GET("search")
fun searchRecipe(
#Query("q") query: String,
#Query("app_id") app_id: String,
#Query("app_key") app_key: String,
#Query("from") from: Int,
#Query("to") to: Int
): Call<RecipeResponse>
Some things to note:
The list of recipes is now a list of Hits with a Recipe
The fields that are in RecipeResponse are not necessarily needed (depending of how you have GSON configured with Retrofit). The hits field is neccesary
By looking into your json and data class does not seems to be matched ..
Few things to be consider
Your json has hits as List but data class does not even have referece to it
By seeing json I assume that your root data is object which have List<Hits> later List<Hits> has receipe as object n later on it contain lists n object
Here is Modified Data class which hold your Json(Given by you)
data class DummyResponse(
#SerializedName("count")
val count: Int = 0,
#SerializedName("from")
val from: Int = 0,
#SerializedName("hits")
val hits: List<Hit>?,
#SerializedName("more")
val more: Boolean = false,
#SerializedName("q")
val q: String = "",
#SerializedName("to")
val to: Int = 0
)
data class Hit(
#SerializedName("bookmarked")
val bookmarked: Boolean = false,
#SerializedName("bought")
val bought: Boolean = false,
#SerializedName("recipe")
val recipe: Recipe?
)
data class Recipe(
#SerializedName("calories")
val calories: Double = 0.0,
#SerializedName("cautions")
val cautions: List<String> = listOf(),
#SerializedName("dietLabels")
val dietLabels: List<Any> = listOf(),
#SerializedName("digest")
val digest: List<Digest> = listOf(),
#SerializedName("healthLabels")
val healthLabels: List<String> = listOf(),
#SerializedName("image")
val image: String = "",
#SerializedName("ingredientLines")
val ingredientLines: List<String> = listOf(),
#SerializedName("ingredients")
val ingredients: List<Ingredient> = listOf(),
#SerializedName("label")
val label: String = "",
#SerializedName("shareAs")
val shareAs: String = "",
#SerializedName("source")
val source: String = "",
#SerializedName("totalDaily")
val totalDaily: TotalDaily?,
#SerializedName("totalNutrients")
val totalNutrients: TotalNutrients?,
#SerializedName("totalTime")
val totalTime: Double = 0.0,
#SerializedName("totalWeight")
val totalWeight: Double = 0.0,
#SerializedName("uri")
val uri: String = "",
#SerializedName("url")
val url: String = "",
#SerializedName("yield")
val yield: Double = 0.0
)
data class Digest(
#SerializedName("daily")
val daily: Double = 0.0,
#SerializedName("hasRDI")
val hasRDI: Boolean = false,
#SerializedName("label")
val label: String = "",
#SerializedName("schemaOrgTag")
val schemaOrgTag: String? = "",
#SerializedName("sub")
val sub: List<Sub> = listOf(),
#SerializedName("tag")
val tag: String = "",
#SerializedName("total")
val total: Double = 0.0,
#SerializedName("unit")
val unit: String = ""
)
data class Sub(
#SerializedName("daily")
val daily: Double = 0.0,
#SerializedName("hasRDI")
val hasRDI: Boolean = false,
#SerializedName("label")
val label: String = "",
#SerializedName("schemaOrgTag")
val schemaOrgTag: String? = "",
#SerializedName("tag")
val tag: String = "",
#SerializedName("total")
val total: Double = 0.0,
#SerializedName("unit")
val unit: String = ""
)
data class Ingredient(
#SerializedName("image")
val image: String? = "",
#SerializedName("text")
val text: String = "",
#SerializedName("weight")
val weight: Double = 0.0
)
data class TotalDaily(
#SerializedName("CA")
val cA: LabelNQuality,
#SerializedName("CHOCDF")
val cHOCDF: LabelNQuality,
#SerializedName("CHOLE")
val cHOLE: LabelNQuality,
#SerializedName("ENERC_KCAL")
val eNERCKCAL: LabelNQuality,
#SerializedName("FASAT")
val fASAT: LabelNQuality,
#SerializedName("FAT")
val fAT: LabelNQuality,
#SerializedName("FE")
val fE: LabelNQuality,
#SerializedName("FIBTG")
val fIBTG: LabelNQuality,
#SerializedName("FOLDFE")
val fOLDFE: LabelNQuality,
#SerializedName("K")
val k:LabelNQuality,
#SerializedName("MG")
val mG: LabelNQuality,
#SerializedName("NA")
val nA: LabelNQuality,
#SerializedName("NIA")
val nIA: LabelNQuality,
#SerializedName("P")
val p: LabelNQuality,
#SerializedName("PROCNT")
val pROCNT: LabelNQuality,
#SerializedName("RIBF")
val rIBF: LabelNQuality,
#SerializedName("THIA")
val tHIA: LabelNQuality,
#SerializedName("TOCPHA")
val tOCPHA: LabelNQuality,
#SerializedName("VITA_RAE")
val vITARAE: LabelNQuality,
#SerializedName("VITB12")
val vITB12: LabelNQuality,
#SerializedName("VITB6A")
val vITB6A: LabelNQuality,
#SerializedName("VITC")
val vITC:LabelNQuality,
#SerializedName("VITD")
val vITD:LabelNQuality,
#SerializedName("VITK1")
val vITK1: LabelNQuality,
#SerializedName("ZN")
val zN: LabelNQuality
)
data class TotalNutrients(
#SerializedName("CA")
val cA:LabelNQuality,
#SerializedName("CHOCDF")
val cHOCDF: LabelNQuality,
#SerializedName("CHOLE")
val cHOLE: LabelNQuality,
#SerializedName("ENERC_KCAL")
val eNERCKCAL: LabelNQuality,
#SerializedName("FAMS")
val fAMS: LabelNQuality,
#SerializedName("FAPU")
val fAPU: LabelNQuality,
#SerializedName("FASAT")
val fASAT: LabelNQuality,
#SerializedName("FAT")
val fAT: LabelNQuality,
#SerializedName("FATRN")
val fATRN: LabelNQuality,
#SerializedName("FE")
val fE: LabelNQuality,
#SerializedName("FIBTG")
val fIBTG: LabelNQuality,
#SerializedName("FOLAC")
val fOLAC: LabelNQuality,
#SerializedName("FOLDFE")
val fOLDFE: LabelNQuality,
#SerializedName("FOLFD")
val fOLFD: LabelNQuality,
#SerializedName("K")
val k: LabelNQuality,
#SerializedName("MG")
val mG: LabelNQuality,
#SerializedName("NA")
val nA: LabelNQuality,
#SerializedName("NIA")
val nIA: LabelNQuality,
#SerializedName("P")
val p: LabelNQuality,
#SerializedName("PROCNT")
val pROCNT: LabelNQuality,
#SerializedName("RIBF")
val rIBF: LabelNQuality,
#SerializedName("SUGAR")
val sUGAR: LabelNQuality,
#SerializedName("THIA")
val tHIA: LabelNQuality,
#SerializedName("TOCPHA")
val tOCPHA: LabelNQuality,
#SerializedName("VITA_RAE")
val vITARAE: LabelNQuality,
#SerializedName("VITB12")
val vITB12: LabelNQuality,
#SerializedName("VITB6A")
val vITB6A: LabelNQuality,
#SerializedName("VITC")
val vITC: LabelNQuality,
#SerializedName("VITD")
val vITD: LabelNQuality,
#SerializedName("VITK1")
val vITK1: LabelNQuality,
#SerializedName("WATER")
val wATER: LabelNQuality,
#SerializedName("ZN")
val zN: LabelNQuality
)
data class LabelNQuality(
#SerializedName("label")
val label: String = "",
#SerializedName("quantity")
val quantity: Double = 0.0,
#SerializedName("unit")
val unit: String = ""
)
P.S: Check your Json response with Api json response . I assume that Apis sending object as root and you are taking it as List<Object>
As your error looks like, your retrofit call returns Recipe object and not a List<Recipe>, check your JSON response and compare it

Categories

Resources