-1

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": []
      }
    }
  ]
}
Mihodi Lushan
  • 670
  • 5
  • 24
Fatih Can
  • 1
  • 1
  • you need to share the stack trace, the line at which you are seeing this error, and minimal code with which you are able to reproduce the issue – sidgate Aug 10 '20 at 17:25
  • @sidgate when i started it normally there are no errors but no load also. In my ListViewModel there are onSuccess and onError functions, I put a breakpoint on both and it gives that error message. "at line 1 column 1 path $" – Fatih Can Aug 10 '20 at 17:41
  • 1
    the error says this is a problem generated when parsing the response. you can add sample format of your response or check yourself. Maybe your response JSON is buggy, the error says so. – Mihodi Lushan Aug 10 '20 at 19:55
  • You need to create the entire class (with subclasses) for you response. I recommend you pass the json (from zomato api) to this page and generate necessary classes http://www.jsonschema2pojo.org/ – isthemartin Aug 10 '20 at 22:06
  • @isthemartin it says to create a data class for nearly all parameters. Do i need to do that to just get name ? – Fatih Can Aug 11 '20 at 17:27
  • 1
    @MihodiLushan I'm gonna add it rightaway – Fatih Can Aug 11 '20 at 17:28
  • your model class had a problem. you needed to wrap with another class to parse the whole JSON object as a Kotlin object first, then inside that you have to receive the list. check my answer to get an idea about how this should be! and yes get yourself familiar with jsonschema2pojo. this is something very helpful like @isthemartin said – Mihodi Lushan Aug 11 '20 at 18:01

1 Answers1

0

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?
)
Mihodi Lushan
  • 670
  • 5
  • 24
  • thanks for reply but should my adapter and listview use RestaurantResponse or List – Fatih Can Aug 11 '20 at 18:11
  • everything else should be the same as before. just keep in mind, you were expecting list directly earlier, now your list is inside a model class. you should pass your list after fetching from your response object. – Mihodi Lushan Aug 11 '20 at 18:14
  • I tried jsonschema2pojo.org and worked, I needed to get all details anyway but just wanted to learn how to use APi as getting just names thank you so much for your help !! @MihodiLushan – Fatih Can Aug 14 '20 at 10:44