json 将 Map<String,String> 传递给 springMVC 控制器

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18280395/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 19:43:22  来源:igfitidea点击:

Passing a Map<String,String> to a springMVC controller

ajaxjsonspringspring-mvc

提问by azpublic

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

我正在尝试将 HashMap 或任何其他 Map 实现从 ajax 发送到 Spring MVC 控制器

Here's the detail of how I do it :

这是我如何做的细节:

the Ajax call is as follow

Ajax 调用如下

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 ?

我究竟做错了什么 ?

Thank you.

谢谢你。

回答by Martin Frey

Binding a map in a spring controller is supported the same way as binding an array. No special converter needed!

在 spring 控制器中绑定地图的支持方式与绑定数组相同。无需特殊转换器!

There is one thing to keep in mind though:

不过有一点要记住:

  • Springuses commandobject(s) as a top level value holder. A command object can be any class.
  • Spring使用命令对象作为顶级值持有者。命令对象可以是任何类。

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

所以你所需要的只是一个包装类 ( TagsWrapper),它包含一个Map<String, String>称为标签的类型的字段。与绑定数组所采用的方法相同。

This is explained pretty well in the docs but i kept forgetting the need of the wrapper object once in a while ;)

这在文档中得到了很好的解释,但我偶尔会忘记包装对象的需要;)

The second thing you need to change is the way you submit the tags values:

您需要更改的第二件事是提交标签值的方式:

  • use one form parameter per map key and not a full string representation of the complete map.
  • one input value should look like this:

      <input type="text" name="tags[key]" value="something">
    
  • 每个地图键使用一个表单参数,而不是完整地图的完整字符串表示。
  • 一个输入值应如下所示:

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

If tags is a map in a wrapper this works out of the box for form submits.

如果标签是包装器中的地图,则这对于表单提交是开箱即用的。

回答by azpublic

Here's my completed answer with code as per Martin Frey's help :

这是我根据 Martin Frey 的帮助用代码完成的答案:

javascript side (note how the tags values are populated):

javascript 方面(注意标签值是如何填充的):

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 with Map inside of it :

并在其中创建包含 Map 的包装类:

class MyWrapper {

    Map<String,String> tags;

   +getters and setters

}

Then you'll get your map populated appropriately ...

然后你会得到你的地图适当地填充......

回答by SJ Arvind

This could be late in the response. However, it might help someone. I had a similar problem and this is how i fixed it. On JS: My Map Looks Like,

这可能会在响应中迟到。但是,它可能会帮助某人。我有一个类似的问题,这就是我修复它的方法。在 JS 上:我的地图看起来像,

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"));
}

回答by soulcheck

You're sending a javascript array tags, which by default will be url-encoded by jQuery as a series of parameters named tags[]. Not sure if this is what you wanted.

您正在发送一个 javascript 数组tags,默认情况下,jQuery 会将其 url 编码为一系列名为tags[]. 不确定这是否是您想要的。

You get an error, because spring doesn't have default conversion strategy from multiple parameters with the same name to HashMap. It can, however, convert them easily to List, array or Set.

你会得到一个错误,因为 spring 没有从多个同名参数到HashMap. 但是,它可以轻松地将它们转换为List、数组或Set.

So try this:

所以试试这个:

@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";
} 

回答by ced-b

The best way of doing this would be encoding the object using JSON and decoding it.

最好的方法是使用 JSON 对对象进行编码并对其进行解码。

You need two libraries. On the client side you need json2.js. Some browsers seem to natively do this by now. But having this is the safer way.

你需要两个库。在客户端,您需要json2.js。一些浏览器现在似乎本身就可以做到这一点。但拥有这种方式是更安全的方式。

On the server you need Hymanson.

在服务器上,您需要Hymanson

On the client you encode your map and pass that as parameter:

在客户端上,您对地图进行编码并将其作为参数传递:

var myEncodedObject = JSON.stringify(tags);

On the server you receive 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 may be some way in Spring to make it convert automatically, but this is the gist of it.

Spring 中可能有一些方法可以让它自动转换,但这是它的要点。