I have to read JSON values from the URL using a query parameter for GET request.
I am using Tomcat latest in a Spring Boot project.
#RequestMapping(
value = "/values",
method = RequestMethod.GET,
headers = HttpHeaders.ACCEPT + "=" + MediaType.APPLICATION_JSON_VALUE,
produces = "application/json")
public ResponseEntity<String> myMethod(
#RequestParam(value="key") String jsonRequestString) {
//parse JSONString
//--
}
GET request to the URL
Url:- http://localhost:port/values?key={"org":"AA","points":[{"name":"xy","Measures":"343"}]}]
Throws
java.lang.IllegalArgumentException: Invalid character found in the request target. The valid characters are defined in RFC 7230 and RFC 3986
EDIT :- Sending JSON in original form leading me to nowhere, so working approach would be to send the JSON in an encoded form.
You can encode the key parameter to Base64 format and append to the URL, then decode and use it in your controller method.
Key JSON text:
{"org":"AA","points":[{"name":"xy","Measures":"343"}]}]
Base64 encoded text:
eyJvcmciOiJBQSIsInBvaW50cyI6W3sibmFtZSI6Inh5IiwiTWVhc3VyZXMiOiIzNDMifV19XQ==
Decoded to again back to JSON text:
{"org":"AA","points":[{"name":"xy","Measures":"343"}]}]
Few things you should take care of.
Use POST HTTP method to post your JSON to server.
Create a JAVA pojo class which should has a same structure as your JSON. Like for below JSON,
{
"id": 123,
"status": "Ordered",
"product": "Pepsi"
}
i would create a class( You can create a two separate class as you has array inside json) ,
public class Order {
private long id ;
private String status;
private String product ;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getProduct() {
return product;
}
public void setProduct(String product) {
this.product = product;
}
}
Then,
#RequestMapping(value = "/values", method = RequestMethod.POST,produces={"application/json"},
consumes={"application/json"})
public ResponseEntity myMethod(
#RequestBody Order orderObj) {
}
Please take reference from this example and build the solution.
You can directly pass String into the JSONObject constructor
There are lots of libraries available.
1.http://www.java2s.com/Code/Jar/j/Downloadjavajsonjar.htm (JSON jar)
2.http://www.java2s.com/Code/Jar/j/Downloadjsonsimple11jar.htm (Simple JSON)
3.http://www.java2s.com/Code/Jar/g/Downloadgson224sourcesjar.htm (GSON from google)
I personally use JSON and GSON jars.
JSONObject jsonObject = new JSONObject(variable)
You can simply try something like this
#GetMapping(value = "/values", produces = MediaType.APPLICATION_JSON_VALUE)
#Timed
public ResponseEntity<String> testMethod(#RequestParam("key") String key) throws Exception {
JSONObject jsonObject = new JSONObject(key);
//
}
Related
Kindly read this question, that is asked by me before some hours:
How is it possible that POST API working in Postman but not the retrofit?
Actually, from Retrofit response, I'm getting response in String format from ResponseBody object.
Explanation: My status code is 200, successful, but from the response body, it is only String. How can I get all data from that String?
After login success, I'm getting String in onResponse. I'm already sending user credential to this APi and in API response, I'm getting this String.
May be there is something encode decode with base64 relation.
public class LoginModel {
#SerializedName("body")
private Body body;
public Body getBody() {
return body;
}
public static class Body {
#SerializedName("userPwd")
private String userpwd;
#SerializedName("prodId")
private int prodid;
#SerializedName("emailId")
private String emailid;
#SerializedName("customerId")
private int customerid;
public String getUserpwd() {
return userpwd;
}
public int getProdid() {
return prodid;
}
public String getEmailid() {
return emailid;
}
public int getCustomerid() {
return customerid;
}
}
}
Now in if you followed this answer you retrofit interface is something like this
#Headers("Content-Type: application/json")
#POST("login/desktop/user")
Call<ResponseBody> getToken(#Body HashMap<String, HashMap<String, Object>> data);
change it to
#Headers("Content-Type: application/json")
#POST("login/desktop/user")
Call<LoginModel> getToken(#Body HashMap<String, HashMap<String, Object>> data); // change here
Now you can get your data in onResponse() like this
LoginModel loginData = response.body();
String pswd = loginData.getBody().getUserpwd();
PS = if you can change the response I suggest you to change var body from response to something else like data.
SerializedName used in POJO class are not important, read more about them here
Hope this will help!
I'm trying to implement a POST method in JSON and I'm not able to do it.
This is my code:
#POST
#Path("/assign")
#Consumes("application/json")
public Response createProjectInJSON(Projecte product) {
String result = "Product created : " + product;
return Response.status(201).entity(result).build();
}
And this is the "Projecte" class:
public class Projecte {
private String titol;
private String estat;
private String professor;
private String data_def, data_crea, data_mod, qualificacio;
private String descripcio, recursos, estudiant, estudi;
public Projecte(String titol, String estat, String professor) {
this.titol = titol;
this.estat = estat;
this.professor = professor;
}
//getters and setters...
I use Postman writing in Body with format JSON the following data:
{
"titol": "hola",
"estat": "proposat",
"professor": "jack"
}
What I'm doing bad? Postman tell me that there is a status of 415 Unsupported Media Type.
What can I do to solve it? Thanks for all!
Miquel
This is mostly likely happening because you didn't set the Content-Type HTTP header to application/json. Clicking on the Headers tab in Postman will allow you to edit the headers directly. More details about headers in Postman can be found here
#RequestBody not accepting the request from the client. Kindly help me to solve this
For testing, I am sending JSON data from postman in raw(application/JSON) to my controller in the below format
Error in postman: The request sent by the client was syntactically incorrect.
But I guess this is the correct format of JSON. Please correct me if am wrong
{
"flight_details": [
{
"flight_from": "Bangalore",
"flight_to": "Hyderabad"
},
{
"flight_from": "Delhi",
"flight_to": "Pune"
}]
}
Here is my controller code:
#RequestMapping(value="addFlightDetails", method = RequestMethod.POST)
public void addOfferTest(HttpServletRequest request, HttpServletResponse
response,#RequestBody RequirementBean requirementbean){
System.out.println("flightdetails:"+requirementbean.getFlight_details());
}
My Bean class:
public class RequirementBean {
private String flight_details;
//Getters and Setters
}
If I am sending the same request in the below format I am able to receive request
{"flight_details":"Bangalore"}
But my desired format is the one which mentioned above.
Please help me to fix this issue
Try this might works for you...
#RequestMapping(value="addFlightDetails", method = RequestMethod.POST)
public void addOfferTest(HttpServletRequest request, HttpServletResponse
response,#RequestBody String json){
JSONObject mainObject=new JSONObject(json);
JSONObject flightdetails=mainObject.getJSONObject("flight_details");
String flight_from=flightdetails.getString("flight_from");
String flight_from=flightdetails.getString("flight_from");
System.out.println(flight_from);
System.out.println(flight_to);
}
let me know any issues...
You send a json array to controller. you need to a list to get this array. It could be like this.
public class FlightDetails{
private String flight_from;
private String flight_to;
//Getters and Setters
}
public class RequirementBean {
private List<FlightDetails> flight_details;
//Getters and Setters
}
Change your RequirementBean code as below
public class RequirementBean {
private List<FlightDetail> flight_details;
//Getters and Setters
}
public class FlightDetail {
private String flight_from;
private String flight_to;
//Getters and Setters
}
You are trying to convert a JSON array to String which is incorrect. You can do it in two ways
1. Create a bean FlightDetails with fields from and to. In this case your controller becomes
#RequestMapping(value="addFlightDetails", method = RequestMethod.POST)
public void addOfferTest(HttpServletRequest request, HttpServletResponse
response,#RequestBody FlightDetails[] requirementbean){ }
Use RequirementBean which contains array or list of FlightDetail beans.
public class RequirementBean {
private List flight_details;
//Getters and Setters
}
Can you try this ?
#RequestMapping(value="addFlightDetails",method=RequestMethod.POST)
public #ResponseBody void addFlightDetails(#RequestBody String data,HttpServletRequest request,HttpServletResponse response,HttpSession session,OutputStream outp) {
DBObject dBObject = new BasicDBObject();
String message = "";
JSONParser parser = new JSONParser();
Object obj = parser.parse(new StringReader(data));
JSONObject jsonObject = (JSONObject) obj;
System.out.println(jsonObject);
}
I am trying to figure out if it is possible to pass a JSON object to rest API, Or pass a multiple parameters to that API ? And how to read these parameters in Spring ? Lets assume that the url looks like the below examples :
Ex.1 http://localhost:8080/api/v1/mno/objectKey?id=1&name=saif
Is it valid to pass a JSON object like in the url below ?
Ex.2 http://localhost:8080/api/v1/mno/objectKey/{"id":1, "name":"Saif"}
Questions:
1) Is it possible to pass a JSON object to the url like in Ex.2?
2) How can we pass and parse the parameters in Ex.1?
I tried to write some methods to achieve my goal, but could not find the right solution?
I tried to pass JSON object as #RequestParam
http://localhost:8080/api/v1/mno/objectKey?id=1 There was an unexpected error (type=Unsupported Media Type, status=415). Content type 'null' not supported
http://localhost:8080/api/v1/mno/objectKey/id=1 There was an unexpected error (type=Not Found, status=404). No message available
http://localhost:8080/api/v1/mno/objectKey/%7B%22id%22:1%7D There was an unexpected error (type=Not Found, status=404). No message available
#RequestMapping(value="mno/{objectKey}",
method = RequestMethod.GET,
consumes="application/json")
public List<Book> getBook4(#RequestParam ObjectKey objectKey) {
...
}
I tried to pass the JSON object as #PathVariable
#RequestMapping(value="ghi/{objectKey}",method = RequestMethod.GET)
public List<Book> getBook2(#PathVariable ObjectKey objectKey) {
...
}
I created this object to hold the id parameter and other parameters like name , etc ....
class ObjectKey{
long id;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
}
(1) Is it possible to pass a JSON object to the url like in Ex.2?
No, because http://localhost:8080/api/v1/mno/objectKey/{"id":1, "name":"Saif"} is not a valid URL.
If you want to do it the RESTful way, use http://localhost:8080/api/v1/mno/objectKey/1/Saif, and defined your method like this:
#RequestMapping(path = "/mno/objectKey/{id}/{name}", method = RequestMethod.GET)
public Book getBook(#PathVariable int id, #PathVariable String name) {
// code here
}
(2) How can we pass and parse the parameters in Ex.1?
Just add two request parameters, and give the correct path.
#RequestMapping(path = "/mno/objectKey", method = RequestMethod.GET)
public Book getBook(#RequestParam int id, #RequestParam String name) {
// code here
}
UPDATE (from comment)
What if we have a complicated parameter structure ?
"A": [ {
"B": 37181,
"timestamp": 1160100436,
"categories": [ {
"categoryID": 2653,
"timestamp": 1158555774
}, {
"categoryID": 4453,
"timestamp": 1158555774
} ]
} ]
Send that as a POST with the JSON data in the request body, not in the URL, and specify a content type of application/json.
#RequestMapping(path = "/mno/objectKey", method = RequestMethod.POST, consumes = "application/json")
public Book getBook(#RequestBody ObjectKey objectKey) {
// code here
}
you can pass multiple params in url like
http://localhost:2000/custom?brand=dell&limit=20&price=20000&sort=asc
and in order to get this query fields , you can use map like
#RequestMapping(method = RequestMethod.GET, value = "/custom")
public String controllerMethod(#RequestParam Map<String, String> customQuery) {
System.out.println("customQuery = brand " + customQuery.containsKey("brand"));
System.out.println("customQuery = limit " + customQuery.containsKey("limit"));
System.out.println("customQuery = price " + customQuery.containsKey("price"));
System.out.println("customQuery = other " + customQuery.containsKey("other"));
System.out.println("customQuery = sort " + customQuery.containsKey("sort"));
return customQuery.toString();
}
Multiple parameters can be given like below,
#RequestMapping(value = "/mno/{objectKey}", method = RequestMethod.GET, produces = "application/json")
public List<String> getBook(HttpServletRequest httpServletRequest, #PathVariable(name = "objectKey") String objectKey
, #RequestParam(value = "id", defaultValue = "false")String id,#RequestParam(value = "name", defaultValue = "false") String name) throws Exception {
//logic
}
Yes its possible to pass JSON object in URL
queryString = "{\"left\":\"" + params.get("left") + "}";
httpRestTemplate.exchange(
Endpoint + "/A/B?query={queryString}",
HttpMethod.GET, entity, z.class, queryString);
When creating or listing and item using REST api I return also the whole resource path.
For example creating a person record returns http://service:9000/person/1234in response. In order to get schema, host & port part like http://service:9000, I extract it from URL obtained by HttpServletRequest.getRequestURL().
Example (not the production code but conceptually same):
#RequestMapping(value = "/person", method = RequestMethod.PUT)
public Object putPerson(
#RequestParam(value = "name") String name,
HttpServletRequest req) {
long id = createPerson(name);
String uriStart = RestUtils.getSchemeHostPortUrlPart(req
.getRequestURL().toString());
String uri = uriStart + "/person/" + id;
Person person = new Person(name, id, uri);
return person; //Serialized to json by Spring & Jackson
}
//Simple bean-like class
public class Person {
//Getter methods for uri, name & id
}
Since this is quite a boiler plate code which repeats in every method I was wondering if Spring does not have support for this which eluded me when reading it's documentation.
By this I mean accessing either URL without neededn HttpServletRequest or even better its schema, host, port part only.
The documentation provides a lot of examples for constructing URIs using a UriComponentsBuilder.
Furthermore I recommend to take a look at Spring HATEOAS if you want to take your REST API to the next level.
BTW: PUT means that you place what you send (request body) to the location to which you send it (URL). If nothing is there something new is created, otherwise what exists is updated (replaced).
This is not what is happening in your example. The proper way would be to either POST to /person or PUT to the person's own URL, e.g. /person/1234, provided you have the ID beforehand.
You can construct the URI in an interceptor (that's executed previous to controller methods) and put it as an attribute and use it in the controller method.
I believe it is quite simple. Look at this example:
#RequestMapping(value = "/person", method = RequestMethod.PUT)
public Object putPerson(#RequestParam(value = "name") String name, HttpServletRequest req) {
long id = createPerson(name);
Person person = new Person(id, name, req);
return person; //Serialized to json by Spring & Jackson
}
public class JsonResponse {
private String url;
public JsonResponse(HttpServletRequest request) {
url = request.getRequestURI() + "?" + request.getQueryString();
}
public final String url() {
return url;
}
}
public class User extends JsonResponse {
private Long id;
private String name;
public User(Long id, String name, HttpServletRequest request) {
super(request);
this.id = id;
this.name = name;
}
// Getter, Setter
}
You can use org.springframework.web.servlet.support.ServletUriComponentsBuilder like this:
String uri = ServletUriComponentsBuilder.fromCurrentRequest()
.replacePath("/person/{id}")
.buildAndExpand(id)
.toUriString();