Send complex json object to Spring MVC controller

2019-09-07 11:21发布

问题:

I am trying to send a complex object to ajax controller for spring mvc search engine, with 3 variables: the current page, items per page and the search parameters. The problem is that with the declaration of the controller method does not take me the params variable as a Map.

As I can send the structure to collect on the controller 3 variables separately?

Error:

Required Map parameter 'params' is not present

  var dataToSend = {
        'page': 1,
        'itemsPerPage': 10,
        'params': {
          'codItem': "10",
          'nameItem': "foo"
        }
      };  

      $.ajax({
        url: form.attr("action"),
        type: 'POST',
        data: JSON.stringify(dataToSend),
        dataType: 'json',
        cache: false
      }).success(function(data) {
        callback(data);
      });        




 public @ResponseBody HashMap<String, Object> search(@RequestParam(value="params") Map<String, String> params, @RequestParam(value = "page") int page, @RequestParam(value = "itemsPerPage") int itemsPerPage){
};

回答1:

To do this properly you need to use JSON library. Spring is bundled with Jackson.

First you need to create class to represent your JSON.

public class MyJson {
  int page;
  int itemsPerPage;
  Map<String, String> params;

  public MyJson() {}

  ... getters/setters

}

You need to change $.ajax, send data like this { data : JSON.stringify(dataToSend)}, becouse parameter need, a name.

In your controller method write this:

ObjectMapper mapper = new ObjectMapper();

// readValue(youStringJson, destinactionClass)
MyJson json = mapper.readValue(data, MyJson.class);

If you have getter for MyJson params field you can iterate over json.getParams() map.



回答2:

/* An Alternative Solution: See if this helps::::Sample Code of java,javascript,jsp for search parameters. Search Parameter POJO will have search parameters + Pagenumber + RecordCounton the page + sortColumn in it */

    public class SearchParameters implements Serializable{
        /**
         * 
         */
        private static final long serialVersionUID = 4847934022647742263L;
        private Integer pageNumber;
        private String sortColumn;
        private Integer recordCount;
        private String sortOrder;
        private Long gdsProductId; // some search parameter
        private Integer ruleId; // some search parameter

    //getter and setters

    }
/* your java controller method, which accepts the SearchParameter Object */

@RequestMapping(value = "/search", method = RequestMethod.POST)
@ResponseBody
public Map<String, GDS> search(SearchParameters parameters)
        throws Exception {
     // Print Parameter 
     logger.info("read :=" + parameters);
     // your logic to be written here
}

/* Your Javascript will have the below function.
   $("#searchPaginationform").serialize() will send the data for all the hidden elements of searchPaginationform in the below jsp.
  form  searchPaginationform will have hidden fields for the pagenumer,rows and other       elements */

    $.post('search.form', $("#searchPaginationform").serialize(), function (response) {

    }
/* Your Jsp -- see the hiddenfield name is matching the SearchParameter instance variable -*/

    <form:form id="searchPaginationform">
        <input type="hidden" name="gdsProductId" id="gdsProductId" >
        <input type="hidden" name="pageNumber" id="pageNumber" value=1>
        <input type="hidden" name="sortColumn" id="sortColumn" value="metamap_id">
        <input type="hidden" name="recordCount" id="recordCount" value=10>
        <input type="hidden" name="sortOrder" id="sortOrder" value="desc">
        <input type="hidden" name="ruleId" id="ruleId"> 
    </form:form>


回答3:

You could simply inject the HttpServletRequest into your Controller method and read the body yourself as shown below :

public @ResponseBody HashMap<String, Object> search(HttpServletRequest request)
{

    String params;
    try 
    {
        params = IOUtils.toString( request.getInputStream());
        System.out.println(params);
    } 
    catch (IOException e) 
    {
        e.printStackTrace();
    }

   //Your return statement.
}  

OutPut : {"page":1,"itemsPerPage":10,"params":{"codItem":"10","nameItem":"foo"}}

You can read this attributes by converting this string into JSON Object by using JSON API sunch as GSON. Or create POJO that contain all your attributes define in JSON and convert your Json strig directly to POJO object.

Sample Code :

MyClass obj = new Gson().fromJson(params, MyClass.class);  

May this help you.



回答4:

I have solved the problem as follows:

public class SearchRequestDto {

  private String page;

  private String itemsPerPage;

  private MultiValueMap<String, List<String>> params;

  }

@ResponseBody
public HashMap<String, Object> buscador(SearchRequestDto searchRequest)
{
}

The problem is that it works for the structure of the example, if I try to pick up the form parameters, sends me not as a json:

  $.ajax({
    url: form.attr("action"),
    type: 'POST',
    data: {  
      'params': form.serialize(),
      'page': start,
      'itemsPerPage': end  
    },
    dataType: 'json',
    cache: false
  }).success(function(data) {
    callback(data);
  });

Result:

itemsPerPage 5
page 1
params codItem=asdfasdf&namItem=asdfasdfasdf&tipItem=1000600&tipItem=1000492&public=on&private=on&provinceItem=15&munItem=262&munItem=270&munItem=276&capItem=123123

And serializeArray():

itemsPerPage 5 page 1

params [10] [name] munItem
params [10] [value] 270
params [11] [name] munItem
params [11] [value] 276
params [13] [name] capItem
params [13] [value] 123123
params [2] [name] codItem
params [2] [value] asdfasdf
params [3] [name] nameItem
params [3] [value] asdfasdfasdf
params [4] [name] tipItem
params [4] [value] 1000600
params [5] [name] tipItem
params [5] [value] 1000492
params [6] [name] public
params [6] [value] on
params [7] [name] private
params [7] [value] on
params [8] [name] provinceItem
params [8] [value] 15
params [9] [name] munItem
params [9] [value] 262

As I can send it as in the structure of dataToSend? the only way is to go through the parameters?



回答5:

My enviroment: AngularJs, SpringMVC, Gson jsonobject

Usually if i send a complex json object from font end to back end, i will do a generic way like below to handle it.

first:

$http({
    method: 'POST',
    url: contextPath+"/voice/submitWrapupForm",
    dataType: 'json',
    data: $.param({
              content : angular.toJson( { array:$(form).serializeArray() })
          }),
    headers: { 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8' }
).success(function (data, status) {
    console.log(data);
});

i use angularJs to submit a formatted json string, i believe using jquery ajax will be the same, just need to be sure that data u sent is json formatted string. https://docs.angularjs.org/api/ng/function/angular.toJson

second:

@RequestMapping(value = "/submitForm", method = RequestMethod.POST,headers = "Accept=application/json")
public @ResponseBody String submitForm(String content) {
    JsonObject j = new Gson().fromJson(content ,JsonElement.class).getAsJsonObject();
    return j.toString();
}

u can watch the json content is pass to mvc controller, and in controller u can use Gson to convert and to json object.