Passing the <String, String> Map to the SpringMVC Controller

I am trying to send a HashMap or any other map implementation from ajax to a Spring MVC controller

Here's the details of how I do this:

Ajax call is as follows

var tags = {}; tags["foo"] = "bar"; tags["whee"] = "whizzz"; $.post("doTestMap.do", {"tags" : tags }, function(data, textStatus, jqXHR) { if (textStatus == 'success') { //handle success console.log("doTest returned " + data); } else { console.err("doTest returned " + data); } }); 

then on the controller side I have:

 @RequestMapping(value="/publisher/doTestMap.do", method=RequestMethod.POST) public @ResponseBody String doTestMap(@RequestParam(value = "tags", defaultValue = "") HashMap<String,String> tags, HttpServletRequest request) { // System.out.println(tags); return "cool"; } 

Unfortunately, I systematically get

 org.springframework.beans.ConversionNotSupportedException: Failed to convert value of type 'java.lang.String' to required type 'java.util.Map'; nested exception is java.lang.IllegalStateException: Cannot convert value of type [java.lang.String] to required type [java.util.Map]: no matching editors or conversion strategy found 

What am I doing wrong?

Thanks.

+7
json spring ajax spring-mvc
source share
5 answers

Map binding in the spring controller is supported in the same way as array binding. No special converter is needed!

One thing to keep in mind:

  • Spring uses the command object as the owner of the top-level value. The object of the command can be any class.

So, all you need is a wrapper class ( TagsWrapper ), which contains a field of type Map<String, String> called tags. The same approach you use to bind an array.

This is explained pretty well in the docs, but I kept forgetting about the need for a wrapper object;)

The second thing you need to change is the way you send the tag values:

  • use one form parameter for each map key, not the full string representation of the full map.
  • one input value should look like this:

      <input type="text" name="tags[key]" value="something"> 

If the tags are a card in the shell, this works out of the box to submit the form.

+10
source share

Here is my completed answer with the code as requested by Martin Frey:

javascript (note how tag values ​​are populated):

 var data = { "tags[foo]" : "foovalue", "tags[whizz]" : "whizzvalue" } $.post("doTestMap.do", data , function(data, textStatus, jqXHR) { ... }); 

And then on the controller side:

 @RequestMapping(value="/publisher/doTestMap.do", method=RequestMethod.POST) public @ResponseBody String doTestMap(@ModelAttribute MyWrapper wrapper, HttpServletRequest request) { } 

and create your wrapper class using the map inside it:

 class MyWrapper { Map<String,String> tags; +getters and setters } 

Then you will receive the corresponding card on the card ...

+3
source share

It may be late in reply. However, this may help someone. I had a similar problem and that is how I fixed it. On JS: My map looks like

 var values = {}; values[element.id] = element.value; 

Ajax:

  $.ajax({ type : 'POST', url : 'xxx.mvc', data : JSON.stringify(values), error : function(response) { alert("Operation failed."); }, success : function(response) { alert("Success"); }, contentType : "application/json", dataType : "json" }); 

Controller:

 @RequestMapping(value = "/xxx.mvc", method=RequestMethod.POST) @ResponseBody public Map<String, Object> getValues(@RequestBody Map<String, Object> pvmValues, final HttpServletRequest request, final HttpServletResponse response) { System.out.println(pvmValues.get("key")); } 
+3
source share

You send an array of javascript tags , which by default will be encoded in jQuery as a series of parameters called tags[] . Not sure if this is what you wanted.

You get an error because spring does not have a default conversion strategy of several parameters with the same name in the HashMap . However, it can easily convert them to List , array or Set .

So try the following:

 @RequestMapping(value="/publisher/doTestMap.do", method=RequestMethod.POST) public @ResponseBody String doTestMap(@RequestParam(value = "tags[]") Set<String> tags, HttpServletRequest request) { // System.out.println(tags); //this probably won't print what you want return "cool"; } 
0
source share

The best way to do this would be to encode the object using JSON and decode it.

You need two libraries. On the client side you need json2.js . It seems that some browsers initially do this. But if it's safer.

On the server you need jackson .

On the client, you encode your card and pass it as a parameter:

 var myEncodedObject = JSON.stringify(tags); 

On the server, you get the parameter as a string and decode it:

 ObjectMapper myMapper = new ObjectMapper(); Map<String, Object> myMap = myMapper.readValue(tags, new TypeReference<Map<String, Object>>); 

There might be some way in Spring to make it automatically converted, but that is its essence.

0
source share

All Articles