不能在 Spring REST 控制器中将 Map 用作 JSON @RequestParam
Cannot use Map as a JSON @RequestParam in Spring REST controller
这个控制器
@GetMapping("temp")
public String temp(@RequestParam(value = "foo") int foo,
@RequestParam(value = "bar") Map<String, String> bar) {
return "Hello";
}
产生以下错误:
{
"exception": "org.springframework.web.method.annotation.MethodArgumentConversionNotSupportedException",
"message": "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"
}
我想要的是用bar
参数传递一些JSON:
http://localhost:8089/temp?foo=7&bar=%7B%22a%22%3A%22b%22%7D,其中 foo
是 7
,bar
是 {"a":"b"}
为什么 Spring 不能进行这种简单的转换?请注意,如果将地图用作 POST
请求的 @RequestBody
,它会起作用。
如果您想使用 Map<String, String>
,您必须执行以下操作:
@GetMapping("temp")
public String temp(@RequestParam Map<String, String> blah) {
System.out.println(blah.get("a"));
return "Hello";
}
而 URL 是:http://localhost:8080/temp?a=b
使用 Map<String, String>
,您将可以访问所有 URL 提供的请求参数,因此您可以添加 ?c=d
并使用 blah.get("c");
[访问控制器中的值=21=]
有关更多信息,请查看:http://www.logicbig.com/tutorials/spring-framework/spring-web-mvc/spring-mvc-request-param/ 部分 将 Map 与 @RequestParam 一起用于多个参数
更新 1:如果您想将 JSON 作为字符串传递,您可以尝试以下操作:
如果你想映射 JSON 你需要定义一个相应的 Java 对象,所以对于你的例子尝试使用实体:
public class YourObject {
private String a;
// getter, setter and NoArgsConstructor
}
然后利用 Jackson 的 ObjectMapper
将 JSON 字符串映射到 Java 实体:
@GetMapping("temp")
public String temp(@RequestParam Map<String, String> blah) {
YourObject yourObject =
new ObjectMapper().readValue(blah.get("bar"),
YourObject.class);
return "Hello";
}
如需进一步 information/different 方法,请查看:JSON parameter in spring MVC controller
以下是有效的解决方案:
只需将 String
到 Map
的自定义转换器定义为 @Component
。然后会自动注册:
@Component
public class StringToMapConverter implements Converter<String, Map<String, String>> {
@Override
public Map<String, Object> convert(String source) {
try {
return new ObjectMapper().readValue(source, new TypeReference<Map<String, String>>() {});
} catch (IOException e) {
throw new RuntimeException(e.getMessage());
}
}
}
这个控制器
@GetMapping("temp")
public String temp(@RequestParam(value = "foo") int foo,
@RequestParam(value = "bar") Map<String, String> bar) {
return "Hello";
}
产生以下错误:
{
"exception": "org.springframework.web.method.annotation.MethodArgumentConversionNotSupportedException",
"message": "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"
}
我想要的是用bar
参数传递一些JSON:
http://localhost:8089/temp?foo=7&bar=%7B%22a%22%3A%22b%22%7D,其中 foo
是 7
,bar
是 {"a":"b"}
为什么 Spring 不能进行这种简单的转换?请注意,如果将地图用作 POST
请求的 @RequestBody
,它会起作用。
如果您想使用 Map<String, String>
,您必须执行以下操作:
@GetMapping("temp")
public String temp(@RequestParam Map<String, String> blah) {
System.out.println(blah.get("a"));
return "Hello";
}
而 URL 是:http://localhost:8080/temp?a=b
使用 Map<String, String>
,您将可以访问所有 URL 提供的请求参数,因此您可以添加 ?c=d
并使用 blah.get("c");
[访问控制器中的值=21=]
有关更多信息,请查看:http://www.logicbig.com/tutorials/spring-framework/spring-web-mvc/spring-mvc-request-param/ 部分 将 Map 与 @RequestParam 一起用于多个参数
更新 1:如果您想将 JSON 作为字符串传递,您可以尝试以下操作:
如果你想映射 JSON 你需要定义一个相应的 Java 对象,所以对于你的例子尝试使用实体:
public class YourObject {
private String a;
// getter, setter and NoArgsConstructor
}
然后利用 Jackson 的 ObjectMapper
将 JSON 字符串映射到 Java 实体:
@GetMapping("temp")
public String temp(@RequestParam Map<String, String> blah) {
YourObject yourObject =
new ObjectMapper().readValue(blah.get("bar"),
YourObject.class);
return "Hello";
}
如需进一步 information/different 方法,请查看:JSON parameter in spring MVC controller
以下是有效的解决方案:
只需将 String
到 Map
的自定义转换器定义为 @Component
。然后会自动注册:
@Component
public class StringToMapConverter implements Converter<String, Map<String, String>> {
@Override
public Map<String, Object> convert(String source) {
try {
return new ObjectMapper().readValue(source, new TypeReference<Map<String, String>>() {});
} catch (IOException e) {
throw new RuntimeException(e.getMessage());
}
}
}