I need to generate the following query string from RetroFit. I know that I can repeat query elements easily enough. Just need it formatted so that each element takes the form of assessment[id][points]=parameter
//Assume Assessment contains the id and the parameter
#PUT("url")
Call putElements(#Query(???) Assessment... assessmentIds);
Example Output:
https://baseurl.com/url?assessment[id1][points]=3&assessment[id2][points]=5
Is there a clean way to accomplish this in RetroFit?
Yes, you're looking for #QueryMap
You will use it like this:
// sender
Map<String,String> parameters = new HashMap<>();
parameters.add("assessmentid1points", "3");
parameters.add("assessmentid2points", "5");
parameters.add("key3", "value3");
yourObject.putElements(parameters);
// receiver interface
#PUT("url")
Call putElements(#QueryMap Map<String,String> parameters);
I've written a few tutorials on Retrofit 1 and 2, in case you want to check them out, here
Related
I have an api that accepts multiple values with same key but different index e.g.
phone_no[0]="1234"
phone_no[1]="5678"
I need to send an array or list of strings that contains phone numbers. I have tried using
#FormUrlEncoded
#POST("get_user_by_phone.php")
Call<PojoGetFriendsListResponse> getUserFromPhone(#Field("phone_no") ArrayList<String> phone_no);
but it generates request body like below
phone_no=%2B1234&phone_no=%2B5678
is there any way to generate a requestbody like this?
phone_no[0]=%2B1234&phone_no[1]=%2B5678
Try This:
HashMap<String, String> phoneNumbers= new HashMap<>();
phoneNumbers.put("phone_no[0]", "99912443432");
phoneNumbers.put("phone_no[1]", "99912443433");
phoneNumbers.put("phone_no[2]", "99912443434");
#FormUrlEncoded
#POST("get_user_by_phone.php")
Call<PojoGetFriendsListResponse> getUserFromPhone(#FieldMap HashMap<String, String> phoneNumbers);
I'm looking for way to add an int array (e.g [0,1,3,5]) as parameter in a GET request with retrofit 2. Then, the generated url should be like this : http://server/service?array=[0,1,3,5]
How to do this ?
Just add it as a query param
#GET("http://server/service")
Observable<Void> getSomething(#Query("array") List<Integer> array);
You can also use int[], or Integer... as a last param;
You need to name your query param with an array syntax like so:
#GET("http://server/service")
Observable<Void> getSomething(#Query("array[]") List<Integer> array);
The syntax itself will vary by the backend technology being used, however not including the brackets "[]" will normally be interpreted as a single value.
For example, using array=1&array=2 will generally be interpreted by backends as only array=1 or array=2 instead of array=[1,2].
I have finally founded a solution by using Arrays.toString(int []) method and by removing spaces in this result because Arrays.toString return "[0, 1, 3, 5]". And my request method looks like this
#GET("http://server/service")
Observable<Void> getSomething(#Query("array") String array);
I faced a similar problem and had to do a couple of things to reach the acceptable form (as asked in the question).
Converted an ArrayList to String
arrayList.toString().replace(" ", "")
In RetroFit method, I changed the Query param which accepts the ArrayList above to as follows:
#Query(value = "cities", encoded = true)
This ensures that the brackets and commas are not URL encoded.
Using toString didn't work for me.
Instead, TextUtils.join(",", ids) does the trick.
Don't forget to mark the Query with encoded = true.
Well this did the trick for me
Step 1 :
In StateServce.kt
#GET("states/v1")
fun getStatesByCoordinates(#Query("coordinates", encoded = true) coordinates: String) : Call<ApiResponse<List<State>>>
Step 2
While calling from repository
val mCoordinate : List<Double> = [22.333, 22.22]
mStateService?.getStatesByCoordinates(mCoordinate.toString().replace(" ", ""))!!
Use Iterable to encapsulate the integer list, or use a two-dimensional integer array.
How to define:
public interface ServerService {
#GET("service")
Call<Result> method1(#Query("array") Iterable<List<Integer>> array);
#GET("service")
Call<Result> method2(#Query("array") Integer[][] array);
}
How to use:
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://server/")
.addConverterFactory(GsonConverterFactory.create())
.build();
ServerService service = retrofit.create(ServerService.class);
// Use the first method.
List<Integer> data1 = Arrays.asList(0,1,3,5);
Iterable array1 = Arrays.asList(data1);
Call<Result> method1Call = service.method1(array1);
// Use the second method.
Integer[] data2 = new Integer[]{0,1,3,5};
Integer[][] array2 = new Integer[][]{data2};
Call<Result> method2Call = service.method2(array2);
// Execute enqueue() or execute() of method1Call or method2Call.
Please refer to the code ParameterHandler.java of Retrofit2 for the reason why the way can solve the problem.
You can pass the value as below
In Repository
getApiResponse(arrayOf(0,1,3,5).contentToString())` In Kotlin.
#GET("http://server/service")
suspend fun getApiResponse(#Query("array") array: String): Response
It will work.
I am using retrofit to communicate with a server.
I want to send a 2d array which would be like this
album[0][uuid]:test
album[0][title]:test
album[0][public_text]:aaaaaalhjkl
album[0][private_text]:aaaaaalhjkl
album[1][uuid]:test2
album[1][title]:test2
album[1][public_text]:aaaaaalhjasdfkl
album[1][private_text]:aaaaaalhasdfjkl
in another call when i needed to send only the uuid i tried this and it worked
Call<response> deleteAlbum(#Header("token") String userToken, #Field("album[][uuid]") ArrayList<String> uuid);
and i'm passing an arraylist of strings and it works fine.
But here i have a more complex pararigm and i don't know what to do.
If I try something like this
Call<response> updateAlbum(#Header("token") String userToken, #Field("album[][uuid]")ArrayList<String> ablumids,#Field("album[][title]")ArrayList<String> title,#Field("album[][public_text]")ArrayList<String> public_text,#Field("album[][private_text]")ArrayList<String> private_text);
the server only reads the first field (uuid) and responds with "there is not enough parameters" . Has anyone any ideas how to solve this?
Thank you
ok so i figured the answer
the call must be
Call<response> updateAlbum(#Header("token") String userToken, #FieldMap Map<String, String> ablumids);
and pass the data like this
HashMap<String, String> t = new HashMap<String, String>();
t.put("album[0][uuid]","test");
t.put("album[0][title]","changeTitleTest2");
t.put("album[0][public_text]","aaaaaalhjkl");
t.put("album[0][private_text]","aaaaaalhjkl");
I don't know if it's the best solution but it works
Hi I have to send map to server and the server will get information from that. I'm having two piece of code for mapping first is(name and key are variables)
String user = "{ 'id':" + userId +","+"'response':{'id':"+userId+",'access':"+"'"+name+":"+key+"'"+"}}";
Map<String, Object> userMap = new Gson().fromJson(user, new TypeToken<HashMap<String, Object>>() {}.getType());
Set<String> keys = userMap.keySet();
for (String i:keys){
Log.d("user",i+" "+userMap.get(i));
}
here I concat required string and parse it and then convert it into map . This piece of code had worked. And my second set of code is
String user1 = "{id="+userId+", access="+""+name+":"+key+""+"}";
Map<String,Object> tuc = new HashMap<>();
tuc.put("id",userId);
tuc.put("access","");
Set<String> key = tuc.keySet();
for (String i:key){
Log.d("user",i+" "+tuc.get(i));
}
this code is not working,that mean server is not accepting this code. But when I print key value pairs the results are same for both codes. My lead doesn't like to use first piece of code. Can any one explain why,I'm struck in this for past two days. Thank you.Sorry for my poor English.
In Java, HashMap can only accept <key, value> pairs. It is not like Json, which in your case is in {key1:value1, key2:value2, ...} format.
Therefore, if you are intended to convert its format from {key1:value1, key2:value2, ...} into <key, value>. My suggestion is combining value2, value3, ... into an object (like String) as the value and value1 as the key.
See https://docs.oracle.com/javase/7/docs/api/java/util/HashMap.html for more details.
I'm trying to pass multiple Values to a SINGLE parameter for example :
http://api.giphy.com/v1/gifs?api_key=dc6zaTOxFJmzC&ids=feqkVgjJpYtjy,7rzbxdu0ZEXLy
I tried the following :
#GET("gifs")
Call<GIFModelMain> getGifsByID(#Field("ids")ArrayList<String> values, #Query("api_key") String API_KEY);
In my activity :
ArrayList<String> x = new ArrayList<>();
x.add("feqkVgjJpYtjy");
x.add("7rzbxdu0ZEXLy");
gifCall = interf.getGifsByID(x, BuildConfig.GIPHY_API_TOKEN);
But the built URL is of form:
http://api.giphy.com/v1/gifsids=feqkVgjJpYtjy&ids=7rzbxdu0ZEXLy&api_key=API_KEY_BLANK
I looked up similar questions but found no correct answer.
EDIT: As per what TooManyEduardos said i changed my Interface to
#GET("gifs")
Call<GIFModelMain> getGifsByID(#QueryMap Map<String, String> parameters,#Query("api_key") String API_KEY);
And my activity is now :
Map<String,String> map = new HashMap<>();
map.put("ids","feqkVgjJpYtjy");
map.put("ids","7rzbxdu0ZEXLy");
gifCall = interf.getGifsByID(map, BuildConfig.GIPHY_API_TOKEN);
But the built URL is still :
03-30 02:46:23.922: E/FavActivity(21607): Url : api.giphy.com/v1/gifs?ids=7rzbxdu0ZEXLy&api_key=KEY_HERE
You're looking for a
Map<String,String>
And in your #Get interface, you'll receive it like this:
(#QueryMap Map<String, String> parameters)
So your whole interface call would be like this:
#GET("gifs")
Call<GIFModelMain> getGifsByID(#QueryMap Map<String, String> parameters);
I wrote a whole tutorial on how to use Retrofit 2 if you want to check it out: http://toomanytutorials.blogspot.com/2016/03/network-calls-using-retrofit-20.html
EDIT
If you really want to pass multiple parameters, regardless of their key name, you can always do this:
Call<GIFModelMain> getGifsByID(#Query("api_key") String API_KEY, #Query("ids") String id1, #Query("ids") String id2, #Query("ids") String id3);
The obvious problem here is that you'll have to make multiple versions of the same method depending on how many ids you're passing