将Map <string,string>传递给springMVC控制器</string,string>

时间:2013-08-16 19:04:46

标签: ajax json spring spring-mvc

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

以下是我如何做的详细信息:

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

然后在控制器方面我有:

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

不幸的是我系统地得到了

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

我做错了什么?

谢谢。

5 个答案:

答案 0 :(得分:11)

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

但有一点要记住:

  • Spring 使用命令对象作为顶级值持有者。命令对象可以是任何类。

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

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

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

  • 每个地图键使用一个表单参数,而不是完整地图的完整字符串表示。
  • 一个输入值应如下所示:

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

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

答案 1 :(得分:4)

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

javascript端(注意如何填充标记值):

var data = {
   "tags[foo]" : "foovalue", 
   "tags[whizz]" : "whizzvalue" 
}

$.post("doTestMap.do",   data , function(data, textStatus, jqXHR) {
    ...
}); 

然后在控制器方面:

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

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

class MyWrapper {

    Map<String,String> tags;

   +getters and setters

}

然后你会适当填充地图......

答案 2 :(得分:4)

这可能是迟到的回应。但是,它可能对某人有所帮助。 我遇到了类似的问题,这就是我修复它的方法。 在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"
        });

控制器:

@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 :(得分:0)

您正在发送一个javascript数组tags,默认情况下,它将由jQuery作为一系列名为tags[]的参数进行url编码。不确定这是不是你想要的。

您收到错误,因为Spring没有从具有相同名称的多个参数到HashMap的默认转换策略。但是,它可以轻松地将它们转换为List,数组或Set

所以试试这个:

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

答案 4 :(得分:0)

执行此操作的最佳方法是使用JSON对对象进行编码并对其进行解码。

您需要两个库。在客户端,您需要json2.js。有些浏览器现在似乎原生这样做了。但这样做更安全。

在服务器上,您需要jackson

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

var myEncodedObject = JSON.stringify(tags);

在服务器上,您将接收参数作为字符串并对其进行解码:

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

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