How can I post following parameter in retrofit through post method ?
"params":{"body": {
"learning_objective_uuids": [
"ED4FE2BB2008FDA9C8133FF462959C0968FAB98C4D1DB8F2"
],
"note": "FasfAFSASFASDF",
"user_uuids": [
"EDF8B7EC20005ACC5C40FF7D6E988801F5BAD83CBBCDB97F",
"EDF8F78F2000569C64101F244AA20C0070D2A7FCB1939E19"
]
}
}
} }
#FormUrlEncoded
#POST("service_name")
void functionName(
#FieldMap Map<String, String> learning_objective_uuids, #FieldMap Map<String, String> user_uuids, #Field("note") String note,
Callback<CallBackClass> callback
);
Better solution : Use arraylist.. Reference link : johnsonsu
#FormUrlEncoded
#POST("service_name")
void functionName(
#Field("learning_objective_uuids[]") ArrayList<String> learning_objective_uuids, #Field("user_uuids[]") ArrayList<String> user_uuids, #Field("note") String note,
Callback<CallBackClass> callback
);
see this example where i need to pass registration fields data as json request
#POST("magento2apidemo/rest/V1/customers")
Call<RegisterEntity> customerRegistration(#Body JsonObject registrationData);
here i have created registrationData is
private static JsonObject generateRegistrationRequest() {
JSONObject jsonObject = new JSONObject();
try {
JSONObject subJsonObject = new JSONObject();
subJsonObject.put("email", "abc#xyz.com");
subJsonObject.put("firstname", "abc");
subJsonObject.put("lastname", "xyz");
jsonObject.put("customer", subJsonObject);
jsonObject.put("password", "password");
} catch (JSONException e) {
e.printStackTrace();
}
JsonParser jsonParser = new JsonParser();
JsonObject gsonObject = (JsonObject) jsonParser.parse(jsonObject.toString());
return gsonObject;
}
As of today, running the Retrofit implementation 'com.squareup.retrofit2:retrofit:2.1.0'
This works perfectly...
#FormUrlEncoded
#POST("index.php?action=item")
Call<Reply> updateManyItem(#Header("Authorization") String auth_token, #Field("items[]") List<Integer> items, #Field("method") String method);
You can disregard the #Header and #Field("method") .... the main piece is #Field("items[]") List<Integer> items
This is what allows you to send the items. On the API side I am simply looking for an array of integers and this works perfectly.
Go to this site : JSON Schema 2 POJO
Paste your example Json format and then
Select source type : JSON , annotation style : None
Create a POJO class then , for example your class name : MyPOJOClass
Then in your Api :
#POST("endpoint")
public Call<Void> postArray(#Body MyPOJOClass mypojoclass);
If you have headers too you can add them in parameters like that :
#Header("Accept") String accept,#Header("Content-Type") String contentType
#Edit : for your comment checkout my answer : how-to-use-gson-2-0-on-onresponse-from-retrofit-2-0
I've found a new workaround:
you can send it as a String:
#POST("CollectionPoints")
#FormUrlEncoded
Call<SomeResponse> postSomething(#Field("ids")String ids);
and send pass it like this:
Call<SomeResponse> call = service.postSomething("0","0", Arrays.toString(new int[]{53551, 53554}));
Best Regards!
Gson is the Best solution for JSON Object/Array related problems.
Here, I am sharing my easiest solution for passing array type value in retrofit API
id: ArrayList<String> //Already initilized
status: String //Already initilized
val jsonObject = JsonObject()
val toJson = Gson().toJsonTree(id) //Only one line to covert array JsonElement
jsonObject.add("id", toJson) //Add Json Element in JsonObject
jsonObject.addProperty("status", status)
API Calling using jsonObject
#POST("API_END_POINT")
fun changeStatusOfList(#Body jsonObject: JsonObject): Observable<Response<RETURN_TYPE>>
Output in Log:
{"id":["426","427"],"status":"1"}
if you want to send a list of the same name the only thing that worked for me in retrofit2 is to use #Query
#FormUrlEncoded
#POST("service_name")
void functionName(
#Query("category") List<Int> categories
);
this will send it like: https://example.com/things?category=100&category=101&category=105
the accepted answers seem not to work in Retrofit2
Related
I'm using Retrofit 2 to call API in Android App. I have a API, using POST, which have a String param in Query Tag. I do everything like doc suppose and I test this API successfully in Test Page. I can run another API correctly so the problem is not the way I use Retrofit 2.
Here is my interface:
#POST("/users/{userId}/get_list_friends")
Call<GetListFriendDataResponse> getListFriend(#Path("userId") int userId, #Query("list") String list, #Query("page") int page, #Query("size") int size, #Header("hash") String hash);
Here is my implementation:
ArrayList<String> id = new ArrayList<>();
id.add("4782947293");
JSONArray jsonArray = new JSONArray(id);
JSONObject jsonObject = new JSONObject();
try {
jsonObject.put("list", jsonArray);
} catch (JSONException e) {
e.printStackTrace();
}
String list = jsonObject.toString();
Log.e(TAG, "list: " + list);
apiInterface.getListFriend(21, list, 1,1,"AHHIGHTJGI").enqueue(new Callback<GetListFriendDataResponse>() {
#Override
public void onResponse(Call<GetListFriendDataResponse> call, Response<GetListFriendDataResponse> response) {
Log.e(TAG, " response code: "+ response.code());
}
#Override
public void onFailure(Call<GetListFriendDataResponse> call, Throwable t) {
}
});
I always get response code: 400 when use this API.
I'm focusing the "list" var. "list" is a JSON text but I wonder if method "jSon.toString()" is right to get a String from a JSONObject, which can using in Retrofit 2. List param form is:{"list":["12332"]} .
Please help me!
Questions
1) Why you are creating JSONObject and JSONArray on your own?
2) You are creating string using whatever you are creating json.
Eg: {list:["123","456"]}
you are trying pass whole json, I think, instead you need to pass just the array of string to the list key.
Request Sending
{
list:["123","456"]
}
suppose the above json is the request you want to send to server
Now, create model class goto http://jsonschema2pojo.org and paste your json and select json and gson at right side and click on preview.
It will show the classes to map you json to model. Use this model class to set the list to the key in your json
I found my problem. The JSON text contains some special character so I need to convert them to URL encode.
Correct request URL like this:
http://54.169.215.161:8080/users/29/add_friend?list=%7B%22list%22%3A%5B%2215536%22%5D%7D&platform=google
By using Retrofit 2, it uses the URL:
http://54.169.215.161:8080/users/29/add_friend?list={%22list%22:[%2215536%22]}&platform=google
So I get Bad Request Response code.
Retrofit 2 also provides method to convert char sequence to URL encode but it 's not enough. So I don't use Retrofit 's convert method by using this code: encode= true.
so my interface is:
#POST("/users/{userId}/get_list_friends")
Call<GetListFriendDataResponse> getListFriend(#Path("userId") int userId, #Query(value = "list",encoded = true) String list, #Query("page") int page, #Query("size") int size, #Header("hash") String hash);
And I manually convert JSON text to URL encode by code:
list = list.replace("{", "%7B");
list=list.replace("]", "%5D");
list=list.replace("[", "%5B");
list=list.replace(":", "%3A");
list=list.replace("}","%7D");
list = list.replace("\"", "%22");
That's all. Now I can get data by using API.
Suggestion: If u have the same problem, check the URL retrofit return in response and compare to correct URL to see special character, which is not converted to URL encode.
I have trouble to send a JSON POST Request to my server.
My server accept a POST with application/json as type and an example would be like this:
{
"name": "Group4",
"users": [
{"email": "user#example.org"},
{"email": "user2#example.org"},
]
}
If I send this by a REST client I get 200 OK as response, everything fine.
My Android client uses the Android Async HTTP Library (http://loopj.com/android-async-http/) and a documentation to the RequestParams class is here https://loopj.com/android-async-http/doc/com/loopj/android/http/RequestParams.html
RequestParams params = new RequestParams();
String userName = getUserName();
List<String> userList = getUserList();
params.put("name", userName);
JSONArray users = new JSONArray();
for(String user : userList) {
JSONObject obj = new JSONObject();
try {
obj.put("email", user);
} catch (JSONException e) {
// ...
}
users.put(obj);
}
params.put("users", users);
I thought this will create exactly a JSON like my example. I don't know if I have the possibility to get a JSON string of this RequestParams. I only can access the parameter as a String:
name=Test&users=[{"email":"user#example.org"}, {"email":"user2#example.org"}]
My server don't even accept the request and fails directly with the error:
AttributeError: 'unicode' object has no attribute 'iteritems'
The problem has to be at the point where I create the RequestParams. Can someone tell me what is wrong with that? I thought I have to create an array with name "users" and then add objects in it with key-value items.
Just put List<> to your RequestParams. Here is the example:
RequestParams params = new RequestParams();
List<String> list = new ArrayList<String>(); // Ordered collection
list.add("Java");
list.add("C");
params.put("languages", list);
//above code will generate url params: "languages[0]=Java&languages[1]=C"
So you don't need to add it manually using Loop sequence.
See the docs here
Will recommend to use Volley for Async calls in Android https://developer.android.com/training/volley/index.html
I need to pass Json in Post request using Retrofit. My Json looks like this:
{
"q": {
"reg": "IND",
"or": [
{
"duration": "12"
}
]
},
"sort": "recent"
}
I created pojo for above Json using jsonschema2pojo which is similar to this: RoomListing.java class
Now I need to make a post request. So I created an API
public interface RoomListingAPI {
#GET("/api/fetch")
void getRoomListing(#Header("x-parse-session-token") String
token, #Body RoomListing list);
}
Created a RestAdapter class
return new RestAdapter.Builder()
.setEndpoint(BASE_URL)
.build();
RoomListingAPI apiservice = restadapter.providesRestAdapter().create(RoomListingAPI.class);
Now I am little bit confused to send Json (Have a look at RoomListing.java) as post request and receive JSON in response ?
Any help would be appreciable.
Firstly, you need to change the annotation from #GET to #POST to do a POST request. Next, assuming you're using Retrofit 1.9.x, you need to do one of two things to get the resulting JSON response, depending on if you want a synchronous or asynchronous response:
Synchronous (on the current thread) - change void to be of the type of the pojo for the response, similar to how you've made your request object (e.g. ResponseType yourMethod(#Body RequestType object);
Asynchronous (on a different thread, with a callback) - add a Callback<ResponseType> to the end of the method, which will then be called on the successful, or unsuccessful, return of the request (e.g. void yourMethod(#Body RequestObject object, Callback<ResponseType> callback);
public interface RoomListingAPI {
#POST("/api/fetch")
void getRoomListing(#Header("x-parse-session-token") String
token, #Field("YOURFIELDNAME") String json);
}
//This method generates your json
private String yourJSON(){
JSONObject jsonRoot = new JSONObject();
JSONObject jsonObject1 = new JSONObject();
JSONArray jsonArray = new JSONArray();
JSONObject jsonObject2 = new JSONObject();
try{
jsonArray.put(jsonObject2);
jsonObject2.put("duration", "12");
jsonObject1.put("reg", "IND");
jsonObject1.put("or", jsonArray);
jsonRoot.put("q", jsonObject1);
jsonRoot.put("sort", "recent");
}catch (JSONException e){
e.printStackTrace();
}
return jsonRoot.toString();
}
RoomListingAPI apiservice = restadapter.providesRestAdapter().create(RoomListingAPI.class);
apiservice.getRoomListing("your_header_token",yourJSON())...
I hope you work but it should be something like this.
I'm working on an Android project which needs a JSONObject for the body of my POST request.
After putting the keys and values of the JSON I got the following line:
{
"xxxx":"zzzzzzz",
"yyyy":"uuuuuuu"
}
But the server got the following:
{
"name_value_pairs": {
"xxxx":"zzzzzzz",
"yyyy":"uuuuuuu"
}
}
I've already tried a JSONStringer but it wasn't really helpful because the Content-Type of the request is application/json.
UPDATE
I'm not trying to construct a JSONObject because it's already done by using the following line of code (the same given by #osayilgan):
JSONObject jsonRequest = new JSONObject();
jsonRequest.put("xxxx", "zzzzzzz");
jsonRequest.put("yyyy", "uuuuuuu");
Here is not the problem. The interface described below is used to communicate with the server.
public interface MyService {
#Headers({"Content-type: application/json",
"Accept: */*"})
#POST("/test")
void testFunction(#Body JSONObject jsonObject, Callback<Response> callback);
}
The server got the request with the second JSON as Body which is disappointing. I note that the key name_value_pairs is automatically added to the object.
Does anybody know how can I fix this?
Issue:
Retrofit by default uses GSON to convert HTTP bodies to and from JSON. The object which is specified with #Body annotation will be passed to GSON for serialization, which basically converts the JAVA object to JSON representation. This JSON representation will be the HTTP request body.
JSONObject stores all the key-value mapping in a member variable by name nameValuePairs.
Here is an excerpt of JSONObject implementation:
public class JSONObject {
...
private final Map<String, Object> nameValuePairs;
...
}
When you pass JSONObject to #Body annotation, this JSONObject is seraliazed, hence the HTTP request body contains : {"nameValuePairs": "actual JSON Object"}.
Solution:
Pass the actual JAVA object to #Body annotation, not it's corresponding JSONObject. GSON will take care of converting it to JSON representation.
For e.g.
class HTTPRequestBody {
String key1 = "value1";
String key2 = "value2";
...
}
// GSON will serialize it as {"key1": "value1", "key2": "value2"},
// which will be become HTTP request body.
public interface MyService {
#Headers({"Content-type: application/json",
"Accept: */*"})
#POST("/test")
void postJson(#Body HTTPRequestBody body, Callback<Response> callback);
}
// Usage
MyService myService = restAdapter.create(MyService.class);
myService.postJson(new HTTPRequestBody(), callback);
Alternative solution:
If you still want to send raw JSON as HTTP request body, then follow the solution mentioned by Retrofit author here.
One of the suggested solution is to use TypedInput:
public interface MyService {
#POST("/test")
void postRawJson(#Body TypedInput body, Callback<Response> callback);
}
String json = jsonRequest.toString();
TypedInput in = new TypedByteArray("application/json", json.getBytes("UTF-8"));
myService.postRawJson(in, callback);
Use com.google.gson.JsonObject instead of org.json.JSONObject.
JSONObject jsonRequest = new JSONObject();
jsonRequest.put("xxxx", "zzzzzzz");
jsonRequest.put("yyyy", "uuuuuuu");
Change to
JsonObject jsonRequest = new JsonObject();
jsonRequest.addProperty("xxxx", "zzzzzzz");
jsonRequest.addProperty("yyyy", "uuuuuuu");
Then in interface
public interface MyService {
#Headers({"Content-type: application/json",
"Accept: */*"})
#POST("/test")
void testFunction(#Body JsonObject jsonObject, Callback<Response> callback);
}
JSONObject class keeping the values in LinkedHashMap with the variable name of nameValuePairs, When Gson trying to convert the JSONObject's instance into JSON,
GSON keeps the structure(which has the variable nameValuePairs). That causing this problem.
you have to covert JSONObject to JsonObject of GSON
follow this way
JsonParser jsonParser = new JsonParser();
JsonObject jsonObject = (JsonObject)jsonParser.parse(actualjsonobject.toString());
then pass in body
HashMap<String,Object> body=new HashMap();
body.put("content",jsonObject);
Thanks to 13KZ, pointed me in the right direction, and to flesh it out here is what I now have to solve this issue.
Definitions
private JsonObject gsonResultTwoWeek;
private JsonObject gsonResultDay;
private JsonObject gsonResult;
Initialise
gsonResult = new JsonObject();
gsonResultDay = new JsonObject();
gsonResultTwoWeek = new JsonObject();
Use
gsonResultDay.addProperty(epoch, value);
where data is a string and value is an int in my case and is in a for loop to add multiple values
And then to pull it all together
gsonResult.addProperty("accounts", 2);
gsonResult.add("todaydata", gsonResultDay);
gsonResult.add("2weekdata", gsonResultTwoWeek);
Finally my interface
public interface ApiInterface {
#POST("/groupdata")
void postGroupData(#Body JsonObject body,Callback<StatusResponse> cb);
}
What hits my server is this
{"accounts":2,"todaydata":{"1423814400":89,"1423816200":150,"1423818000":441},"2weekdata":{"1423699200":4869,"1423785600":1011}}
My solution is based on 13KZ's
public class MyRequest {
#SerializedName(Constants.ID)
private String myID;
#SerializedName(Constants.PARAM_ANSWERS)
private JsonObject answers;
public MyRequest(String id, Hasmap<String, String> answers) {
this.myID = id;
this.answers = new JsonObject();
for (String s: answers.keySet()) {
this.answers.addProperty(s, answers.get(s));
}
}
}
JSONObject jsonRequest = new JSONObject();
try {
jsonRequest.put("abc", "test");
jsonRequest.put("cba", "tye");
} catch (JSONException e) {
e.printStackTrace();
}
Log.d("jsonobject", "onClick: "+jsonRequest);
(result: {"abc":"test","cba":"tye"})
JsonParser jsonParser = new JsonParser();
JsonObject jsonObject = (JsonObject)jsonParser.parse(jsonRequest.toString());
Log.d("jsonobjectparse", "onClick: "+jsonObject);
(result: {"abc":"test","cba":"tye"})
Once you are put the values into the jsonObject pass to the jsonParser it will solve the issue
thats all. enjoy your coding.
nameValuePairs in retfrofit error
get this type
{
"nameValuePairs": {
"email": "mailto:test1#gmail.com",
"password": "12345678"
}
}
need this type
{
"email": "mailto:test1#gmail.com",
"password": "12345678"
}
#POST("login")
suspend fun getLogin(#Body jsonObject: RequestBody) : Response<LoginModel>
In Repository Class
Add this line for conver in json utf-8 fomat
val body = jsonObject.toString().toRequestBody("application/json; charset=utf-8".toMediaTypeOrNull())
class LoginRepository constructor(private val retrofitService: RetrofitService) {
suspend fun getLogin(jsonObject: JSONObject): NetworkState<LoginModel> {
val body = jsonObject.toString().toRequestBody("application/json; charset=utf-8".toMediaTypeOrNull())
val response = retrofitService.getLogin(body)
return if (response.isSuccessful) {
val responseBody = response.body()
if (responseBody != null) {
NetworkState.Success(responseBody)
} else {
NetworkState.Error(response)
}
} else {
NetworkState.Error(response)
}
}
}
It appears that you are attempting to transmit the actual JSONObject rather the the JSON text-string representation of the object. A look at the specification for the JSONObject class shows that you should be using the .toString() method to get the JSON text representation of the data structure kept by the JSONObject. Thus, you should be able to change:
public interface MyService {
#Headers({"Content-type: application/json",
"Accept: */*"})
#POST("/test")
void testFunction(#Body JSONObject jsonObject, Callback<Response> callback);
}
to:
public interface MyService {
#Headers({"Content-type: application/json",
"Accept: */*"})
#POST("/test")
void testFunction(#Body String jsonObject.toString(), Callback<Response> callback);
}
The only change being JSONObject jsonObject to String jsonObject.toString().
Alternately, you could brute force it by just taking the string that you have have of the JSON and replace '"name_value_pairs": {' with '' and the last '}' in the string with ''. JSON is just a string of text. Other than it being inelegant, there is no reason that you can not manipulate the text. Those two replacements will result in a valid JSON text-object. The whitespace indentation won't look correct to a human, but a machine parsing the JSON string does not care if the whitespace is correct.
How I can convert any object (eg array) in json and get in the format string?
For example:
public String jsonEncode(Object obj) {
return jsonString;
}
You can use GSON library to convert any serializable objects into json String.
Here is the Tutorial how-do-convert-java-object-to-from-json-format-gson-api/
If you're asking how to do generic object serialization into json format in java, use reflection. Luckily, lots of the work is done for you, for example this or this.
If you want to go the other way, or specificially you want more control over your serialization, you can still use reflection with annotations. See the jackson mapper
For example:
Hashtable<String, String> capitales = new Hashtable<String, String>();
capitales.put("España", "Madrid");
capitales.put("Francia", "Paris");
String miStringArray[] = { "String1", "String2" };
And I do:
SONObject obj = new JSONObject();
try {
obj.put("name", "Jack Hack");
obj.put("score", miStringArray);
obj.put("otracosa", capitales );
} catch (JSONException e) {
e.printStackTrace();
}
System.out.println(obj);
Show:
{"score":"[Ljava.lang.String;#413587d0","otracosa":"{Portugal=Lisboa, Francia=Paris, Argentina=Buenos Aires, España=Madrid}","name":"Jack Hack"}