I have trouble with Spring MVC and json.
I use SimplecartJS to generate json data like this :
{"currency":"RUR",
"shipping":250,
"tax":0,
"taxRate":0,
"itemCount":2,
"item_name_1":"Name of product #1",
"item_quantity_1":6,
"item_price_1":159,
"item_options_1":"",
"item_name_2":"Name of product #2",
"item_quantity_2":2,
"item_price_2":159,
"item_options_2":"",
"form":{
"Fname":"UserName",
"Phone":"7123456789",
"Address":"UserAddress",
"Comment":"Comment Text"
}
}
My controller Spring
#RequestMapping(value = "/checkorder2", method = RequestMethod.POST, headers = "Accept=application/json")
public String test (#RequestBody OrderCon orderC)throws Exception{
ObjectMapper om = new ObjectMapper();
om.canSerialize(OrderCon.class);
System.out.println(om);
return test(orderC);
}
Code from client side
var url = 'http://localhost:8080/url'
jQuery.ajax({
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
contentType:'application/json',
dataType: "json",
type: "POST",
url: url,
data: JSON.stringify(data),
And my question:
When I send data to controller, I have a mistake 400 Bad request. The request sent by the client was syntactically incorrect. When adding a new item field name will "item_name_2","item_name_3" etc. How I can parse this. I try parse to List, Set but it is not working. Please help.
UPD1: OrderCon.java
public class OrderCon {
private List<String> form;
private List<List<String>> json;
getters and setters...
}
There is no way you are going to be able to parse that data to a class like you have, since you need to add dynamic properties to a Java class.
You do however have two options to get the data out
First option is parse the json to a HasMap of Strings, ie. change your controller signature to
public String test (#RequestBody Map<String, String> orderC)
The other option is to use a JsonNode and deal with the data as a tree, here is an example http://wiki.fasterxml.com/JacksonTreeModel
I personally would try the latter first
You're getting 400 Bad Request because Spring is trying to map the passed JSON directly to your OrderCon class.
For this to work, the class would need to map to the keys specified in the JSON.
IE:
JSON:
{
"name" : "foo",
"phone": "111-111-1111"
}
would map to:
public class someJsonPojo(){
String name;
String phone;
//setters & getters
}
I don't think this will work well since instead of getting an array of items, you only get an item appended to the list as a new key:value. You should be able to modify the JSON so that you can map to an array of Item objects, which contain the name, quantity, price, etc.
Related
I have a request like that:
let jsonData= {};
jsonData["className"]= className;
jsonData["models"]= arr;
let endPoint= "/classses?classAndModel=" + encodeURIComponent(JSON.stringfy(jsonData));
return $.ajax({
url: host + endPoint,
data: data,
cache: false,
contentType: false,
processData: false,
method: "POST"
});
I want to convert that json to java object.I tried this one
My rest service is:
#PostMapping(value=/classes",consumes=MediaType.MULTIPART_FORM_DATA_VALUE)
public ResponseEntity<Void> addClassAndModelMapping(ClassAndModels classAndModels){
}
public class ClassAndModels {
ClassAndModelResult classAndModel;
...getter and setter...
}
public ClassAndModelResult {
String className;
List<String> models;
...getter and setters...
}
I get 400 error.If I change that line ClassAndModelResult classAndModel to String classAndResult.I get response but I want Object type.Do you have any idea?
The first part of code shows that you are sending data as a query string.
Take a look at https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/bind/annotation/RequestParam.html
But considering the #PostMapping, you should send that data in the request body and do something like this on the server side.
#PostMapping("/classes")
public ResponseEntity<Void> addClassAndModelMapping(#RequestBody ClassAndModels classAndModels){
//
}
As Phils says, you can add a GetMapping on your controller to see how your ClassAndModels its being serialized
Source: https://spring.io/guides/tutorials/bookmarks/
P.S. Sorry about my english, I'm not a native speaker.
Please try to add #RequestParam annotation or better use classAndModel value as RequestBody similar to the below.And also correct the spelling mistake in the javascript url.
#PostMapping(value = "/classes")
public ResponseEntity<Void> addClassAndModelMapping(#RequestBody ClassAndModels modal) {
}
I am new to java and creating some Restful services in netbeans using jersey framework.
I have created many GET, POST web services which is having different different type of responses which are basically Model Objects and depending upon media type I am getting JSON or XML.
Some response is having only a single object which is being shown in JSON inside {}, and some are list which are in [].
I want to see a generic response format for all api responses.
Example-
{"status":"0 or 1", "message":"any string message","result":"it can be a single object or a list of objects which is dynamic depending upon each web service response"}.
Since here in java we need to created model objects for getting responses so I have created a ResponseModel which is having a status property , message property but don't know the type of result property because sometime it can have a single object or sometime a list so what type should I set for this property so that I can assign any thing to this and response will always be in same format for JSON or XML.
I have created a static method with constructor which takes all these three parameters and create a ResponseModel object.
Thanks in advance
EDITED- Code after Using "Object" as generic type
public static Response getResponseObjectIsValid(boolean isValid, String message,Object result)
{
if (isValid == true) {
LGSResponse response = new LGSResponse();
response.setStatus(1);
response.setMessage(message.length()>0 ? message : "Success");
response.setResult(result);
return Response.status(Status.OK).entity(response).build();
}
else
{
LGSResponse response = new LGSResponse();
response.setStatus(1);
response.setMessage(message.length()>0 ? message : "Failed");
response.setResult(result);
return Response.status(Status.OK).entity(response).build();
}
}
Result Parameter is a normal model object.
You can simply create your class as you've said.
public class ResponseModel {
int status;
String message;
Object result;
// contructor, getters, setters go here...
// (probably consider using lombok, but that is a story for another time)
}
Then you can pass either a single object or an array as the 3rd param and the json/xml serializer should take care of the conversion for you unless your objects are very complex(I rarely run into that problem)
For example, your Jersey methods would look something like this:
// returning a single object within the response model
#GET
#Path("/myMethod")
public Response aJerseyMethod() {
Book aBookObject = new Book("The Title", "Name of Author");
ResponseModel responseModel = new ResponseModel(1, "This is a book", aBookObject);
return Response.ok(responseModel)
.build();
}
// returning an array within the response model
#GET
#Path("/myOtherMethod")
public Response anotherJerseyMethod() {
Book aBookObject = new Book("The Title", "Name of Author");
Book anotherBookObject = new Book("The Other Title", "Name of another Author");
ArrayList<Book> aBookArray = new Arraylist();
aBookArray.add(aBookObject);
aBookArray.add(anotherBookObject);
ResponseModel responseModel = new ResponseModel(1, "These are books", aBookArray);
return Response.ok(responseModel)
.build();
}
In both cases you should get the expected output you were talking about and you do not have to do any additional checks or conversions yourself.
I just wrote this here, so try it out with your own classes instead of "Book" (which is not a real class) and let me know if it works.
You should not maintains status code, message and result within json body.
Response message should only contain the result of that api.
Httpstatus code will be the status code (Ex.200 is success, 404 is notfound)
All the other info should be maintained in response headers, not within json body
I get a list of object from server. One key of this objects is called body, and it is a json. It is almost impossible for me to know its keys : the key name and size of it (body) are different.
Example of data
data from server = [object, object, object,.....]
object = {
id: 1,
name: "xyz",
body": {
x: "xyz",
y: "xyz",
z: "xys",
}
}
I edit the body and then post it to the server together with the id of the object. Until here it is fine. I can send the request but can not handle the Requestparam which is of type json.
How to handle this post request on the backend built in Java and Spring?
You have to add a #RequestBody annotation to the method on the Controller such as:
#RequestMapping ("url/to/save")
#ResponseBody
public ResponseObject send (#RequestBody RequestObject myRequestObject)
{
//do something
return new ResponseObject ();
}
The RequestObject would be the Java Class mapping to the JSON you want to save. The ResponseObject is whatever you want to return, you could also return void but Firefox has issues with that sometimes.
I am trying to return a model object from spring mvc controller back to jquery ajax method but it is returning blank as the response
jsp:
$( "#dialog-link10" ).click(function( event ) {
var appname= $("#dialog-link10").text();
alert(appname);
if(appname == 'RS Applications') {
$.ajax({
type : "GET",
url : 'abc.html',
dataType: 'JSON' ,
data:
{"id" : $("#dialog-link10").text()}
,
success : function(data) {
alert('success')
alert('data')
}
});}
controller:
#RequestMapping(method=RequestMethod.GET, value="/abc")
#ResponseBody
public Model helloWorld2( #RequestParam("id") String id, Model model) {
System.out.println("*****"+id);
List <String> list1=new ArrayList<String>();
List <String> list2=new ArrayList<String>();
System.out.println("here");
list1.add("abc");
list1.add("abc2");
list1.add("abc3");
list1.add("abc4");
model.addAttribute("list1", list1);
return model;
}
This is not generating success alert as well.
Please suggest
Your method should return directly the list, as a json, no need to put it in the model and return the model. Also check if you have an error in your callback ajax.
You are specifying dataType: 'JSON' in your ajax call, but you are not converting your response object (model) to json in your controller.
From the jQuery ajax documentation for dataType setting:
The type of data that you're expecting back from the server. If none is specified, jQuery will try to infer it based on the MIME type of the response (an XML MIME type will yield XML, in 1.4 JSON will yield a JavaScript object, in 1.4 script will execute the script, and anything else will be returned as a string)
You'll probably want to reference a json serializer (unless you want to write your own) - but the important part is serializing your model to json in your response. For example (using json-io):
String jsonModel = JsonWriter.objectToJson(model);
return jsonModel;
You can then access the string array contained in your json response object in the following way:
success : function(data) {
for (i = 0; i < data.list1.length; i++){
alert(data.list1[i]);
}
}
And a fiddle example for reading json objects
I met this problem and it took me several hours to find out the problem.
Just remove "Model model" from your parameter.
Use a Map<String, String> or Map<String, Object> instead.
Try adding the produces = MediaType.APPLICATION_JSON to the RequestMapping annotation
#RequestMapping(method=RequestMethod.GET, value="/abc", produces = MediaType.APPLICATION_JSON)
Also, you may not need the Model paramater in the method.
I'm trying to build a REST api for my application. The basics are done. But now I need some help to for a search with different parameters and their operands.
Let's say I have a JSON String like this:
{"v00Datvon":"09-07-2014","v00Datbis":"09-07-2014","v00Saicode":{"saiCode":"SO02"}}
These are values of my "contract" domain object.
For the search at the UI part, you can choose for the two dates an operand (greater or less or equals)
All the parameters (without the operands) are sent per GET and Ajax call.
The Spring MVC Controller looks like this:
#RequestMapping(value = "/", method = RequestMethod.GET, headers = "Accept=application/json")
public ResponseEntity<String> getContractsFromSearch(#RequestParam String allRequestParams, ModelMap model){
//some stuff
}
I'm looking for technical input, how to add the operands to the JSON String and Controller in a clean and good way. I dont want to hack some bad code.
If you need more input, please leave a comment.
Thanks!
Update 1.
GET Request:
allRequestParams={"v00Datvon":"09-07-2014","v00Datbis":"09-07-2014","v00Saicode":{"saiCode":"SO02"}}
Update 2.
{
"dateFrom": {
"dateFrom": "someDate",
"operand": "less"
},
"dateTo": {
"dateTo": "someDate",
"operand": "greater"
},
"season": {
"season": "someSeason",
"operand": "equals"
}
}
Update 3
Deserialization:
public static Contract fromJsonToContract(String json) {
return new JSONDeserializer<Contract>().use(Calendar.class, new CalendarTransformer("dd-MM-yyyy HH:mm")).use(null, Contract.class).deserialize(json);
}
First of all as per your Controller how you passing Map as requestParam,That can't possibile,Have you try this
#RequestMapping(value = "/", method = RequestMethod.GET, headers = "Accept=application/json")
public ResponseEntity<String> getContractsFromSearch(HttpServletRequest request, Object> allRequestParams, ModelMap model){
Enumeration paramNames = request.getParameterNames();
while(paramNames.hasMoreElements())
{
String paramName =
(String)paramNames.nextElement();
out.print(paramName);
}
//some stuff
}
I think your JSON is too verbose: you have an entry named "dateFrom" that has an entry named "dateFrom", try to keep it simple and "flat". What about this option?:
{
"dateFrom": "someDate",
"operandFrom": "less",
"dateTo": "someDate",
"operandTo": "greater",
"season": "someSeason",
"operandSeason": "equals"
}
I know that group data by semantic is tempting, but in a GET request you have to think the best way to process the parameters.The data can be easily transformed to:
dateFrom=someDate&operandFrom=less&dateTo=someDate&operandTo=greater&season=someSeason&operandSeason=equals
or just send one parameter with the JSON as value:
q={"dateFrom": "someDate","operandFrom":"less","dateTo":"someDate","operandTo":"greater","season":"someSeason","operandSeason":"equals"}
But then you'd need to parse it in your controller.