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
Related
Why is price null here?
JSON is retrieved from here (you could also use multiple parameters, that is why the below object uses Maps; example). Here is CoinGeckoCoinPrice:
public class CoinGeckoCoinPrice {
#Expose
private Map<String, Map<String, Double>> price;
public double getPrice(String slug, String pair) {
...
}
}
Here is my Retrofit2 call:
#GET("/api/v3/simple/price")
Call<CoinGeckoCoinPrice> getCoinPrice(#Query("ids") String coinSlugs, #Query("vs_currencies") String pairs);
I checked logcat for any GSON error message and there is none. So why would price be null?
It works if I change Retrofit2 call to use JsonObject:
#GET("/api/v3/simple/price")
Call<JsonObject> getCoinPrice(#Query("ids") String coinSlugs, #Query("vs_currencies") String pairs);
But I want to wrap the object so I can write data retrieval functions in the CoinGeckoCoinPrice class.
The Json you are getting back doesn't have a price property on it, so Gson doesn't know that it should be parsing the bitcoin object and its price in USD to that object. Given that your returned data can be for any key (i.e. bitcoin, ethereum...) and its properties can also have any keys (i.e. usd, euros...) you'll need to manually parse this by giving Gson a custom adapter to work with.
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 am trying to save data in my firebase such that it appear like this:
I know that the way to input it manually in firebase is ["marie", "femmehacks"]
But how to I input it from android using delimiter..Note that I need to use Java 7 and String.join is not the solution in android.
Here are my codes:
StringBuilder newstring = new StringBuilder();
for (String movie: movies){
newstring.append(movie);
newstring.append(",");
}
String all = newstring.toString();
all = all.substring(0, all.length() - ",".length());
The output as per this code is now:
["marie,femmehacks"]
but I want it to appear like
["marie", "femmehacks"]
such that it is saved in firebase as per the image above. Any help?
Use this function TextUtils.join(CharSequence delimiter, Iterable tokens).
I got this from here https://developer.android.com/reference/android/text/TextUtils#join(java.lang.CharSequence,%20java.lang.Iterable)
android.text.TextUtils
public static String join(#NonNull CharSequence delimiter,
#NonNull Iterable tokens)
External annotations available:
Parameter delimiter: #android.support.annotation.NonNull
Parameter tokens: #android.support.annotation.NonNull
You may try like this. its works for me.
List<String> stringList = new ArrayList<>();
private String membersName = "";
for (UserInfo userInfo : userInfoList) {
stringList.add(userInfo.getUsername());
}
membersName = TextUtils.join(", ", stringList);
you can save like :
FirebaseDatabase.getInstance().getReference().child(“ChildName”).setValue(membersName);
You should push data as ArrayList<String>
ArrayList<String> movies = <enter code to get list>
FirebaseDatabase.getInstance().getReference().child(“yourChild”).setValue(movies);
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 need to send this request to my API
?name=yourname&address=youraddress&phone=1245689&email=me#mail.com&gender=M&birth_date=01011998&birth_place=Surabaya&job=myjob .. other 7 string parameters .. &skills[]=skill1&skills[]=skill2
I could do it like this How to post array in retrofit android
But, is there a simple way to do it in retrofit using #Body rather than #Field/#FieldMap?
I have resolved this by following this answer, but if you are to lazy and has made tons of code and don't want to rewrite them, just use List<Object> myObject = new ArrayList<Object>(); (using my own code as example) :
class UserFormRequest {
private String name;
private String address;
...
private List<SkillObject> skills = new ArrayList<SkillObject>(); // this
}