Modernization: how to specify parameters separated by commas in the request?

I am trying to reorganize my code to use Retrofit (from Volley) for some Foursquare API calls, but have not found a suitable example that shows how to specify a query parameter that has 2 comma separated values.

My base link is as follows:

public static final String VENUES_BASE_URL = "https://api.foursquare.com/v2/venues"; 

The rest of my URL looks like this:

 "?ll=40.7,50.2&limit=50&radius=25000&v=20140909&venuePhotos=1&oauth_token=xxyyxx"; 

1st implementation for my interface:

 public interface Fourquare { @GET("/explore?ll={p1},{p2}&limit=50&radius=25000&v=20140905&venuePhotos=1&oauth_token=xxyyxx") Response getVenues(@Path("p1") String param1, @Path("p2") String param2); } 

And then I made a request like this:

 RestAdapter restAdapter = new RestAdapter.Builder() .setEndpoint(ConfigConstants.VENUES_BASE_URL) .build(); Fourquare fourquare = restAdapter.create(Fourquare.class); Response myResponse = fourquare.getVenues("50", "75"); 

However, the above gave me the following error:

 retrofit.RetrofitError: Fourquare.getVenues: URL query string "ll={p1},{p2}&limit=50&radius=25000&v=20140905&venuePhotos=1&oauth_token=xxyyxx" must not have replace block. 

2nd implementation (After looking at some SO answers using query parameters. NOTE: After I figure out the call to the ll? Parameter, I will get the token as a parameter):

 @GET("/explore&limit=50&radius=25000&v=20140905&venuePhotos=1&oauth_token=xxyyxx") void getVenues(@Query("ll") String ll, Callback<String> cb); 

With an actual call like this:

 fourquare.getVenues("50,75", new Callback<String>() { @Override public void success(String s, Response response) { Log.d(TAG, "Successful run!"); } @Override public void failure(RetrofitError error) { Log.d(TAG, "Failed run!"); } }); 

In the above implementation, the error () method is always called, so there is still something wrong with my code. Can someone give some advice on how to properly make this call? I'm sure the problem is with "ll?" parameter.

Update: after enabling registration, this is the last URL I get from Retrofit: https://api.foursquare.com/v2/venues/explore&limit=50&radius=25000&v=20140909&venuePhotos=1&oauth_token=xxyyxx?ll=30.26%2C-97.74

It seems that Foursquare server does not like the ll parameter at the end of the URL, and it should be explicitly placed immediately after .. / v2 / venues / explore, since it works fine when it sends a request through the browser.

Any solutions to get around this API restriction?

3rd implementation (09/17/14) With the colriot sentence , I managed to resolve the 400 response code that I received with my previous implementation. I still have a speed problem in GSON, so I'm looking for suggestions on how to fix this. In particular, my implementation of Retrofit requires more time to display my results compared to Volley, so I wonder if there is a better way to implement a callback.

Foursquare Interface

 public interface Fourquare { @GET("/explore?limit=50&radius=25000&v=20140909&venuePhotos=1&oauth_token=xxyyxx") void getVenues(@Query("ll") String ll, Callback<Object> cb); } 

RestAdapter call

 RestAdapter restAdapter = new RestAdapter.Builder() .setEndpoint(ConfigConstants.VENUES_BASE_URL) .build(); Foursquare foursquare = restAdapter.create(Foursquare.class); foursquare.getVenues("30.26,-97.74", new Callback<Object>() { @Override public void success(Object o, Response response) { Log.d(TAG, "Success!"); // Parse response GsonBuilder gsonBuilder = new GsonBuilder(); Gson gson = gsonBuilder.create(); JsonParser parser = new JsonParser(); String response2 = gson.toJson(o); JsonObject data = parser.parse(response2).getAsJsonObject(); // Populate data model MetaResponse metaResponse = gson.fromJson(data.get("meta"), MetaResponse.class); VenuesExploreResponse myResponse = gson.fromJson(data.get("response"), VenuesExploreResponse.class); // Store results from myResponse in List } @Override public void failure(RetrofitError error) { Log.d(TAG, "Failures!"); } }); 

Currently, the problem with the above callback implementation is that it takes longer (about 1 second) to analyze and display the results than using Volley. The GsonBuilder / Gson / JsonParser block is exactly the same as in my Volley onResponse (String response) method, except for this intermediate object response2, so most definitely this intermediate / extra step is the bottleneck. I am looking for suggestions on how best to implement Gson parsing. If this is better than a new / separate question, I will do it.

+10
android retrofit foursquare
source share
5 answers

So, as we already found out, the problem was in ?& typo. But another thing to mention is that Retrofit can accept complex objects as call parameters. Then String.valueOf(object) is called to convert the object to the Query / Path parameter.

In your case, you can define a custom class as follows:

 class LatLng { private double lat; private double lng; ... @Override public String toString() { return String.format("%.1f,%.1f", lat, lng); } } 

And reorganize your endpoint method as follows:

 @GET("/explore?limit=50&radius=25000&v=20140905&venuePhotos=1&oauth_token=xxyyxx") void getVenues(@Query("ll") LatLng ll, Callback<String> cb); 

About the analysis of the answer:

  • Never create Gson objects directly in a callback. It is just too heavy. Use the one you provide with the RestAdapter .
  • Why are you mixing JsonParser and Gson ? These are different tools to solve the same problem.
  • Use the mechanism of the built-in Retrofit converter;)

From word to code:

 public class FoursquareResponse<T> { private MetaResponse meta; private T response; // getters } 

Total:

 @GET("/explore?limit=50&radius=25000&v=20140905&venuePhotos=1&oauth_token=xxyyxx") void getVenues(@Query("ll") LatLng ll, Callback<FoursquareResponse<VenuesExploreResponse>> cb); ... foursquare.getVenues(LatLng.valueOf(30.26, -97.74), new Callback<FoursquareResponse<VenuesExploreResponse>>() { @Override public void success(FoursquareResponse<VenuesExploreResponse> r, Response response) { MetaResponse metaResponse = r.getMeta; VenuesExploreResponse myResponse = r.getResponse(); // Store results from myResponse in List } @Override public void failure(RetrofitError error) { Log.d(TAG, "Failures!"); } }); 
+11
source share

Just enter urlencode arguments separated by comma, comma =% 2

0
source share

Try to add all query parameters (fixed and variables) in a valid order. I mean

 @GET("/explore") Response getVenues(@Query("ll") ll, @Query("limit") limit, @Query("radius") radius, @Query("v") v, @Query("venuePhotos") venuePhotos, @Query("oauth_token") oauth_token); 

and end the call with a function with fixed parameters as a constant

0
source share

You can use @EncodedQuery :

 @GET("/explore&limit=50&radius=25000&v=20140905&venuePhotos=1&oauth_token=xxyyxx") void getVenues(@EncodedQuery("ll") LatLng ll, Callback<String> cb); 
0
source share

If you use kotlin and you have var items: List<String> which should be specified as the request parameter.

Use this method to form a string:

 fun itemsString() = items.joinToString(separator = ",") 

Your url should be like this:

 @Query(value = "items", encoded = true) String items 
0
source share

All Articles