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
Related
I'm using volley and trying to make request to API that I'm working on. Json Request should be like this format.
{
"name": "API name",
"param":{
"email": "user#mail.com",
"password": "password"
}
}
I've tried to use hashmap but I don't know how to put
<string string>
<string, hashmap>
this is getting complicated.
Now, how should I put these values in hashmap and convert it to JSONObject and send request to server.
If this is not the way it should be done, then what should I use instead?
HahMap can not be used for JSON serialization, I suggest you to use org.json (https://mvnrepository.com/artifact/org.json/json)
Ex:
JSONObject jsonObj = new JSONObject();
JSONObject param = new JSONObject();
param.put("email","blhablah");
param.put("password","blhablah");
jsonObj.put("name", "apiName");
jsonObj.put("param", param);
System.out.println(jsonObj.toString());
This will give you the json, like follwoing :
{"param":{"password":"blhablah","email":"blhablah"},"name":"apiName"}
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
I am asking this question based on the answers in this link
POST request via RestTemplate in JSON
I actually wanted to send JSON from client and receive the same at REST server. Since the client part is done in the link I mentioned above. For the same how would I handle that request at server end.
CLIENT:
// create request body
JSONObject request = new JSONObject();
request.put("username", name);
request.put("password", password);
// set headers
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<String> entity = new HttpEntity<String>(request.toString(), headers);
// send request and parse result
ResponseEntity<String> loginResponse = restTemplate
.exchange(urlString, HttpMethod.POST, entity, String.class);
if (loginResponse.getStatusCode() == HttpStatus.OK) {
JSONObject userJson = new JSONObject(loginResponse.getBody());
} else if (loginResponse.getStatusCode() == HttpStatus.UNAUTHORIZED) {
// nono... bad credentials
}
SERVER:
#RequestMapping(method=RequestMethod.POST, value = "/login")
public ResponseEntity<String> login(#RequestBody HttpEntity<String> entity) {
JSONObject jsonObject = new JSONObject(entity.getBody());
String username = jsonObject.getString("username");
return new ResponseEntity<>(username, HttpStatus.OK);
}
This gives me 400 bad request error at client side. Hoping for some clues about how to handle this at server side.
HTTPEntity should not be used in your server method. Instead use the argument which is being passed to HTTPEntity from your client. In your case it has to String since you are passing string from client. Below code should work for you.
#RequestMapping(method=RequestMethod.POST, value = "/login")
public ResponseEntity<String> login(#RequestBody String jsonStr) {
System.out.println("jsonStr " + jsonStr);
JSONObject jsonObject = new JSONObject(jsonStr);
String username = jsonObject.getString("username");
return new ResponseEntity<String>(username, HttpStatus.OK);
}
My advice is to create bean class and use it in server and client instead of converting it to String. It will improve readability of the code.
When using the Spring RestTemplate, I usually prefer to exchange objects directly. For example:
Step 1: Declare and define a data holder class
class User {
private String username;
private String password;
... accessor methods, constructors, etc. ...
}
Step 2: Send objects of this class to the server using RestTemplate
... You have a RestTemplate instance to send data to the server ...
// You have an object to send to the server, such as:
User user = new User("user", "secret");
// Set HTTP headers for an error-free exchange with the server.
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
// Generate an HTTP request payload.
HttpEntity<User> request = new HttpEntity<User>(user, headers);
// Send the payload to the server.
restTemplate.exchange("[url]", [HttpMethod], request, User.class);
Step 3: Configure a ContentNegotiatingViewResolver on the server
Declare a bean of the type ContentNegotiatingViewResolver in the Spring XML or Java configuration. This will help the server automatically bind HTTP requests with bean objects.
Step 4: Receive the request on the server
#RestController
#RequestMapping("/user")
class UserAPI {
#RequestMapping(method = RequestMethod.POST)
#ResponseBody
public User create(User user) {
// Process the user.
// Possibly return the same user, although anything can be returned.
return user;
}
}
The ContentNegotiatingViewResolver ensures that the incoming request gets translated into a User instance without any other intervention.
Step 5: Receive the response on the client
// Receive the response.
HttpEntity<User> response = restTemplate.exchange("[url]", [HttpMethod], request, User.class);
// Unwrap the object from the response.
user = response.getBody();
You will notice that the client and the server both use the same bean class (User). This keeps both in sync as any breaking change in the bean structure would immediately cause a compilation failure for one or both, necessitating a fix before the code is deployed.
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 am attempting to add some Book(title, author, year) into my book table in a server using an AsyncTask, but i am getting missing bookobject as JSONfrom the method addBook(from the server). So i made a bookObject like this:
JSONObject jObj = new JSONObject();
jObj.put("title", "JAVA");
jObj.put("author", "me");
jObj.put("year", 2005);
After that, i wanna use(my intention is to send this book Object):
List<NameValuePair> nameValuePairs = new ArrayList<>(1);
nameValuePairs.add(new BasicNameValuePair(jObj)); //Error
new AaaBookAsyncTask(this).execute(new Pair<>(nameValuePairs, httpClient));
The problem is BasicNameValuePaircannot applied to JSONObject, but now how can i send the book Object? - Any help or hints is very appreciated.Thanks, Carl
You could send the JSON as a string and then decode it on your server before storing it in your database.