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.
Related
I just want to ask on how to or possible to request a GET in retrofit using the JSON as Query?
for example:
https://www.mywebsite.com/api/location?data=["1"]
https://www.mywebsite.com/api/location?data=["1","2"]
So far, this is what I did, and maybe I think this is wrong?
#GET("/api/location")
fun getLocationData(#Query("data") data: String) // data value = "["1", "2"]"
any help is appreciated! Thanks.
This is an example of what I have:
In this example, with #Path you can add the variable in the url
#GET(Constante.HERO_DETAIL + "/{hero_id}")
Call<DataMaster> getHeroDetail(
#Path("hero_id") Integer hero_id
);
Other example:
#GET(Constante.HERO_LIST)
Call<DataMaster> getHeroList(
#Query("token") String token,
#Query("gameLevel") String gameLevel,
#Query("section") String section
);
I think you are in a good way.
Regards!
Try below
#GET("/api/location/data={x}")
fun getLocationData(#Query("x") myarrdata: String)
I'm using Retrofit 2 and I need to send request body. The problem is somehow the value is converted to string. On the example below, you can see that items and totalPrice which should be array and number respectively are converted to string.
{ cashierId: 'fff7079c-3fc2-453e-99eb-287521feee63',
items: '[{"amount":3,"id":"602a79e3-b4c1-4161-a082-92202f92d1d6","name":"Play Station Portable","price":1500000.0}]',
paymentMethod: 'Debt',
totalPrice: '4500000.0' }
The desired request body is
{ cashierId: 'fff7079c-3fc2-453e-99eb-287521feee63',
items: [{"amount":3,"id":"602a79e3-b4c1-4161-a082-92202f92d1d6","name":"Play Station Portable","price":1500000.0}],
paymentMethod: 'Debt',
totalPrice: 4500000.0 }
Here's the service
#POST("api/sales")
#FormUrlEncoded
Call<Sale> createSale(
#FieldMap Map<String, Object> fields
);
And this is how I call createSale
Map<String, Object> fields = new HashMap<>();
fields.put("cashierId", UUID.fromString("fff7079c-3fc2-453e-99eb-287521feeaaa"));
fields.put("totalPrice", totalPrice);
fields.put("paymentMethod", paymentMethod);
fields.put("items", jsonArray);
Call<Sale> call = retailService.createSale(fields);
Is it possible to send those values as number and array, not as string?
The conversion most certainly happens because you are using #FormUrlEncoded.
According to the documentation:
Field names and values will be UTF-8 encoded before being URI-encoded in accordance to RFC-3986.
A solution would be to use a model class instead of a Map. I see you already have a Sale class. If it looks like something like this:
public class Sale {
String cashierId;
int totalPrice;
String paymentMethod;
ArrayList<SomeObject> items;
}
you can simply do like this:
// in service
#POST("api/sales")
Call<Sale> createSale(#Body Sale sale);
// when doing the call
Sale sale = new Sale();
// set everything in your object
// then
Call<Sale> call = retailService.createSale(sale);
I need to make GET request using Retrofit and one of the parameters is an array of key-value par, or actually, an array of arrays, that looks like this:
[ [1, 10], [50, 100] ]
I figured out how to perform this request in POSTMAN:
Key: durations[0][0] Value: 1
Key: durations[0][1] Value: 10
and so on.
However, I have no idea ho to represent this for Retrofit.
Thank you for help.
EDIT:
I tried to represent it as #Query("durations[]") List<List<Integer>> duration; Single entry is a List with two values, start and end. No luck.
I advise you to use this method
Object get( #Query("durations[0][0]") int value1,#Query("durations[0][1]") int value2,
#Query("durations[1][0]") int value3,#Query("durations[1][1]") int value4)
So basically this is how I solved this. I just manually built the parameter strings I need and put it into a Map along with value. And in your Retrofit interface make filed as #QueryMap:
#QueryMap Map<String, Integer> durations,
Have a look at my method that makes parameters:
public void prepareDurations(Pair<Integer, Integer> durationValues) {
Map<String, Integer> paramsMap = new HashMap<>();
if(durationValues!=null) {
paramsMap.put("durations[0][0]", durationValues.first);
paramsMap.put("durations[0][1]", durationValues.second);
setDuration(paramsMap);
}else {
setDuration(new HashMap<>());
}
}
I need to send a list / an array of Integer values with Retrofit to the server (via POST)
I do it this way:
#FormUrlEncoded
#POST("/profile/searchProfile")
Call<ResponseBody> postSearchProfile(
#Field("age") List<Integer> age
};
and send it like this:
ArrayList<Integer> ages = new ArrayList<>();
ages.add(20);
ages.add(30);
ISearchProfilePost iSearchProfile = gsonServerAPIRetrofit.create(ISearchProfilePost.class);
Call<ResponseBody> call = iSearchProfile.postSearchProfile(
ages
);
The problem is, the values reach the server not comma separated. So the values there are like age: 2030 instead of age: 20, 30.
I was reading (e.g. here https://stackoverflow.com/a/37254442/1565635) that some had success by writing the parameter with [] like an array but that leads only to parameters called age[] : 2030.
I also tried using Arrays as well as Lists with Strings. Same problem. Everything comes directly in one entry.
So what can I do?
To send as an Object
This is your ISearchProfilePost.class
#FormUrlEncoded
#POST("/profile/searchProfile")
Call<ResponseBody> postSearchProfile(#Body ArrayListAge ages);
Here you will enter the post data in pojo class
public class ArrayListAge{
#SerializedName("age")
#Expose
private ArrayList<String> ages;
public ArrayListAge(ArrayList<String> ages) {
this.ages=ages;
}
}
Your retrofit call class
ArrayList<Integer> ages = new ArrayList<>();
ages.add(20);
ages.add(30);
ArrayListAge arrayListAge = new ArrayListAge(ages);
ISearchProfilePost iSearchProfile = gsonServerAPIRetrofit.create(ISearchProfilePost.class);
Call<ResponseBody> call = iSearchProfile.postSearchProfile(arrayListAge);
To send as an Array List check this link https://github.com/square/retrofit/issues/1064
You forget to add age[]
#FormUrlEncoded
#POST("/profile/searchProfile")
Call<ResponseBody> postSearchProfile(
#Field("age[]") List<Integer> age
};
Retrofit can do this now at least I tested with this -> implementation 'com.squareup.retrofit2:retrofit:2.1.0'
For example
#FormUrlEncoded
#POST("index.php?action=item")
Call<Reply> updateStartManyItem(#Header("Authorization") String auth_token, #Field("items[]") List<Integer> items, #Field("method") String method);
This is the piece we are looking at.
#Field("items[]") List<Integer> items
How to pass endpoints in annotations(ex:#GET("dynamic value"))dynamically.
We tried passing values as static and it was doing good but when i pass the values dynamically it is showing the below error
Attribute value must be constant.
It seems that you want to do somthing like this:
#GET("users/list?country={country}")
Call<List<Repo>> listRepos(#Path("country") String country);
where you give the country code when you call the function
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com/")
.build();
GitHubService service = retrofit.create(GitHubService.class);
Try this :
#Documented
#Target(METHOD)
#Retention(RUNTIME)
public #interface GET {
//new
int Endpoints () default 1; (or use enum)
String value() default "";
}