I have some Java REST ws handling POST data from a simple HTML form.
I want to make the client code send to the ws the right JSON to make the server code populate my objects the right way.
I have the following data structure:
public class CarDTO
{
String id;
String defaultName;
List<CarCategoryDTO> carCategoryDTOs;
List<CarTranslationsDTO> carTranslationsDTOs;
/* getter, setter, constructors*/
}
public class CarCategoryDTO
{
String id;
String defaultName;
/* getter, setter, constructors*/
}
public class CarTranslationsDTO
{
int id;
String name;
LanguageDTO languageDTO;
/* getter, setter, constructors*/
}
public class LanguageDTO
{
String code;
/* getter, setter, constructors*/
}
POST Action:
#POST
#Path("/save")
public Response saveCar(String args)
{
try
{
Gson g = new GsonBuilder().create();
CarDTO carDTO = g.fromJson(args, CarDTO.class);
System.out.println(carDTO);
return Response.ok(g.toJson(carDTO)).build();
} catch (Exception e) {
e.printStackTrace();
return Response.serverError().build();
}
}
Client code:
<form id="form_car"
enctype="application/json"
action="http://www.someurl.com:8080/rest/0.1/car/save"
method="POST">
<input type="text" name="defaultName" />
<input type="hidden" name="carTranslationsDTOs[0][languageDTO][code]" value='en'>
<input type="text" name="carTranslationsDTOs[0][name]">
<input type="text" name="carCategoryDTOs[0][defaultName]" value="cat1">
<input id="submitbutton" type="button" value="Salva"/>
</form>
<script>
jQuery("#submitbutton").click(function(){
var formData = JSON.stringify(jQuery("#form_car").serializeObject());
jQuery.ajax({
url: "http://www.someurl.com:8080/rest/0.1/car/save",
type:"POST",
data:formData,
contentType:"application/json; charset=utf-8",
dataType:"json",
success: function(data){
console.log(data);
}
});
});
</script>
I also added the following jQuery extension, but it wasn't enough: jquery.serializeObject.js
The problem is the mapping with Collection of parameters, the result is that I can populate only CarDTO.id and CarDTO.defaultName.
How can I make it work?
EDIT 25/03/2015:
I figured up that the simplest way to solve my problem is to make the json manually from javascript at the submit, tough this don't satisfy me because a lot of the logic is client side, and exposing all my DTO structures in this way is awful.
I didn't know of any custom deserialization in Gson, I think that's the right path to follow.
Any other help and different opinions are well accepted.
You'll likely need to process the JSON until it's in a form that Gson can recognize, i.e. something along the lines of:
{
"defaultName": "Ford",
"carCategoryDTOs": [{
"defaultName": "cat1"
}],
"carTranslationsDTOs": [{
"name": "Ford",
"languageDTO": {
"code": "en"
}
}]
}
If you still run into issues, you may need to write a custom deserializer, see the Writing a Deserializer section of the Gson User Guide.
Note that you're naming conventions for your carTranslationsDTOs is off. Since it's already a has_many relationship, and each carTranslationsDTOs is actually a single translation, this should be named carTranslationDTOs according to your convention.
Your JSON doesn't map to your data structure; the following is the result JSON using your code:
{
"defaultName":"default car name",
"carTranslationsDTOs[0][languageDTO][code]":"en",
"carTranslationsDTOs[0][name]":"car name in en",
"carCategoryDTOs[0][defaultName]":"cat1"
}
While GSON expects something like
{
"defaultName":"default car name",
"carCategoryDTOs":[{"defaultName":"cat1"}],
"carTranslationsDTOs":[{"name":"car name in en",languageDTO:{"code":"en"}}],
}
I wrote a jQuery plugin that serializes/deserializes flat and nested html form data to / from javascript / json. I haven't tried in your particular case but as far as I can see it might solve the problem.
Just have a look at https://github.com/omanshardt/jquery-uicForm3.git.
Related
Heyy,
I want to take a list of data in my request param,here "personIdCollection" is a set of list but when i am hitting through postman i am getting a bad request.
Here is my code.
controller
#PostMapping("/face-tag-data")
public String getFaceTaggedData(#RequestParam String projectId,#RequestParam List<String> personIdCollection) {
return null;
}
and here is my ajax
var data = {};
data.personIdCollection = personIdCollection;
data.projectId = $("#projectId").val();
$.ajax({
type:'POST',
url:contextPath+'/face-tag-data',
data:data,
success:function(resp){
console.log(resp);
},
failure:function(resp){
console.log(resp);
}
});
This is working for me. I do not use an ajax-request but instead submit my form directly but it should work either way.
My controller looks like:
#RequestMapping(value="addSingleArticles", method=RequestMethod.POST)
public #ResponseBody String addSingleArticles(
ArticleSubmitData pupilPackageData,
HttpServletRequest request) {
... // do something with the data
}
As you can see I have defined my own composite type which consists of three lists. So you obviously can use it with only one list directly.
public class ArticleSubmitData {
private List<Article> singleArticles;
private List<Article> packageArticle;
private List<Article> popupArticles;
... // getter & setter, inner classes etc.
}
In my server page oder faclet I use the following html-code to make this work
...
<input id="" class="" type="text" name="singleArticles[${line.index}].engraving" />
...
So the trick is to define the variables on your webpage as an array and use this in your controller as a list. As you can see in my example I also use an inner class in my composite class which has extra attributes.
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 need to access the data being input through the Magnolia script template, from the Magnolia Java model.
I have tried setting up parameters and definitions. I have tried using different properties of the definition and content Node.
public FormModel(Node content, ConfiguredTemplateDefinition definition, RenderingModel<?> parent) {
super(content, definition, parent);
}
public String execute() {
HttpServletRequest request = MgnlContext.getWebContext().getRequest();
if ("POST".equals(request.getMethod())) {
try {
//Access the name input from the template script
}
catch(Exception e) {
System.out.print(e);
}
}
return super.execute();
}
}
<form method="post">
<div>
<label>Name:</label>
<input type="text" name="name"/>
</div>
</form>
I want to be able to access the value of input in the Java code.
You need to specify the modelClass attribute in your template definition, and FormModel should extend info.magnolia.rendering.model.RenderingModelImpl<>. You didn't specify if you did any of these, so it's very hard to guess what might be wrong there.
If you're using YAML, the definition should look like this:
renderType: freemarker
templateScript: /my-module/templates/components/home.ftl
modelClass: my.awesome.FormModel
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.
I've a problem sending data from jQuery to struts2 action class.
I have seen the question: JSON Jquery to Struts2 action but I don't understand the solution quite well.
Here is my problem:
The json array is like this:
[{"id":"1","code":"111","name":"ddd"},
{"id":"2","code":"222","name":"sss"},
{"id":"3","code":"333","name":"eee"}]
I want to send the json data to the struts2 action class.
The jQuery code is like this:
var data = JSON.stringify(dataObj);
$.ajax({
url: "Update",
type: "post",
data: data,
dataType: 'json',
contentType:"application/json;charset=utf-8",
success : function(){
alert("You made it!");
}
});
However, in Chrome's Development Tool, I have seen the data submitted to the server side. But on the server side, I don't know how receive the json data.
Action:
public class Update extends ActionSupport{
private String data;
public String getData(){
return data;
}
public void setData(String data){
this.data= data;
}
public String execute(){
System.out.println(data);
return SUCCESS;
}
}
In this way, data is null.
I've also tried to use a List to receive JSON data. Changing "data" type from String to List<Node>, it failed again. Probably because I don't quite understand the OGNL model which Struts2 is using.
Please Help Me. Thank you very much!
{"id":"1","code":"111","name":"ddd"}
Step 1 : Create a bean/pojo to accumulate/encapsulate the above fields
class MyBean{
String id,code,name;
//getters & setters
}
Step 2 : Change your action code to receive a List of MyBeans
public class Update extends ActionSupport{
private List<MyBean> data;
//other code, getters & setters
}
Step 3: Configure your action to de-serialize JSON data and fill the action fields (using json-plugin)
<action name="Update" class="Update">
<interceptor-ref name="defaultStack"/>
<interceptor-ref name="json">
<param name="enableSMD">true</param>
</interceptor-ref>
</action>
Step 4 : Make necessary changes in the ajax request body being sent to match the action-params/fields
var data = JSON.stringify(dataObj);
$.ajax({
url: "Update",
type: "post",
data: "data:"+data,
dataType: 'json',
contentType:"application/json;charset=utf-8",
success : function(){
alert("You made it!");
}
});
The above code is untested.
Hey The problem is you are directly posting array of objects. So Struts2 don't know whicch method to call. Change your json data like below. Then it will work.
{"data":[{"id":"1","code":"111","name":"ddd"},
"id":"2","code":"222","name":"sss"},
{"id":"3","code":"333","name":"eee"}]}
Then inside the setter read with object
public void setData(List < Report > data) {
System.out.println("Setter Call Flow");
this.data = data;
}
Where Report is a java class contains id,code,name as it's members with setters and getters.