将JSON Map传递给Spring MVC控制器

20

我正在尝试将一个Map对象的JSON表示作为POST参数发送到我的控制器。

@RequestMapping(value = "/search.do", method = RequestMethod.GET, consumes = { "application/json" })
public @ResponseBody Results search(@RequestParam("filters") HashMap<String,String> filters, HttpServletRequest request) {
       //do stuff
}

我发现使用 @RequestParam 会直接抛出 500 错误,所以我尝试使用 @ModelAttribute。

@RequestMapping(value = "/search.do", method = RequestMethod.GET, consumes = { "application/json" })
public @ResponseBody Results search(@ModelAttribute("filters") HashMap<String,String> filters, HttpServletRequest request) {
       //do stuff
}

代码能够正确响应请求,但我发现Map是空的。经过后续试验,我发现任何对象(不仅仅是HashMap)都会被实例化,但没有填充字段。 我的classpath中有Jackson,并且我的控制器将响应JSON。然而,似乎我的当前配置不允许Spring通过GET/POST参数读取JSON。

如何将客户端AJAX请求的JSON对象从请求参数传递到Spring控制器并获得一个Java对象?

编辑 添加了相关的Spring配置

  <bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
    <property name="mediaTypes">
      <map>
        <entry key="html" value="text/html" />
        <entry key="json" value="application/json" />
      </map>
    </property>
    <property name="viewResolvers">
      <list>
        <bean class="org.springframework.web.servlet.view.UrlBasedViewResolver">
          <property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
          <property name="prefix" value="/WEB-INF/jsp/" />
          <property name="suffix" value=".jsp" />
        </bean>
      </list>
    </property>
    <property name="defaultViews">
      <list>
        <bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView">
          <property name="prefixJson" value="true" />
        </bean>
      </list>
    </property>
  </bean>
  <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
    <property name="messageConverters">
      <list>
        <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"/>
      </list>
    </property>
  </bean>

在一位评论员的建议下,我尝试使用 @RequestBody。只要 JSON 字符串用双引号引起来,这种方法就可以工作。

@RequestMapping(value = "/search.do", method = RequestMethod.POST, consumes = { "application/json" })
public @ResponseBody Results<T> search(@RequestBody HashMap<String,String> filters, HttpServletRequest request) {
      //do stuff
}

这解决了我的直接问题,但我仍然好奇如何通过AJAX调用传递多个JSON对象。


你的 spring-context.xml 文件中是否有 MappingJacksonJsonView bean? - Deividi Cavarzan
你是如何发布数据的,作为表单的一部分,还是ajax请求? - clav
@DeividiCavarzan 我的上下文中确实有MappingJacksonJsonView。我正在将这些数据作为AJAX请求发送。我已经尝试使用GET和POST进行操作,但效果相同。 - monitorjbl
这是我的问题,有人可以帮忙吗?http://stackoverflow.com/questions/16409036/springmvc-ajax-request-looking-for-conversion-strategy - devdar
一个类的转换策略是如何完成的? - devdar
显示剩余7条评论
6个回答

7
这解决了我的问题,但我仍然好奇如何通过AJAX调用传递多个JSON对象。 最佳方法是创建一个包含您想要传递的两个(或多个)对象的包装器对象。然后,将您的JSON对象构建为两个对象的数组,例如:
[
  {
    "name" : "object1",
    "prop1" : "foo",
    "prop2" : "bar"
  },
  {
    "name" : "object2",
    "prop1" : "hello",
    "prop2" : "world"
  }
]

然后在您的控制器方法中,您将请求正文作为单个对象接收并提取其中包含的两个对象。例如:

@RequestMapping(value="/handlePost", method = RequestMethod.POST, 
                consumes = {      "application/json" })
public void doPost(@RequestBody WrapperObject wrapperObj) { 
     Object obj1 = wrapperObj.getObj1;
     Object obj2 = wrapperObj.getObj2;

     //Do what you want with the objects...


}

包装对象看起来会像这样...
public class WrapperObject {    
private Object obj1;
private Object obj2;

public Object getObj1() {
    return obj1;
}
public void setObj1(Object obj1) {
    this.obj1 = obj1;
}
public Object getObj2() {
    return obj2;
}
public void setObj2(Object obj2) {
    this.obj2 = obj2;
}   

}

感谢你的RequestBody回答。我在我的请求中有一个Map,但它总是为空,导致响应也为空。现在在Map前加上RequestBody解决了这个问题! - Aliya

2
您可以使用Jackson库将Json转换为Map。
@web-context.xml
<bean id="messageAdapter" class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
    <property name="messageConverters">
        <list>
            <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter" />
        </list>
    </property>
</bean>

@Maven依赖:

<dependency>
    <groupId>org.codehaus.jackson</groupId>
    <artifactId>jackson-core-lgpl</artifactId>
    <version>1.9.13</version>
</dependency>
<dependency>
    <groupId>org.codehaus.jackson</groupId>
    <artifactId>jackson-mapper-lgpl</artifactId>
    <version>1.9.13</version>
</dependency>

@Controller

@RequestMapping(value = "/method", method = RequestMethod.DELETE)
public String method(
                @RequestBody Map<String, Object> obj){

@Request (e.g. jquery Ajax)

$.ajax({"type": "DELETE",
        "contentType": "application/json;",
        "url": "/method",
        "data": JSON.stringify({"key": "Ricardo"}),
        "dataType": "json";}
});

使用Python框架或Play!更加容易。


2
Jackson 1.9.x处于维护模式中,我建议使用Jackson 2.3.x。 - Emerson Farrugia

1
我已经使用以下代码将Map对象传递到Java中: Javascript 代码:
var values = {
                    "object1" : JSON.stringify(object1),
                    "object2" : JSON.stringify(object2)
            };
 var response = $http.post(url,data);

服务器端代码:

@RequestMapping(value = "/deleteData",method = RequestMethod.POST,consumes = MediaType.APPLICATION_JSON_VALUE)
    @ResponseBody
    public Result deleteData(@RequestBody HashMap<String, Object> dataHashMap) {
    Object1 object1=  (Object1) JsonConvertor.jsonToObject((String) dataHashMap.get("object1"), Object1.class);
        Object2 object2= (Object2) JsonConvertor.jsonToObject((String) dataHashMap.get("object2"), Object2.class);   
}

JsonConvertor 类:

public class JsonConvertor {
  public static <T> Object jsonToObject(String json, Class<T> clazz) {
    if (json == null)
      throw new IllegalArgumentException("null cannot be converted to Object");
    Gson gson = new GsonBuilder().disableHtmlEscaping().setDateFormat("dd-MMM-yyyy").create();
    return gson.fromJson(json, clazz);
  }
}

你忘了说明JsonConvertor是什么。 - kryger
1
根据建议修改了解决方案。 - Sanchi Girotra

0

像@dario的答案一样,但适用于Jackson 2版本:

spring-web-context.xml

    <bean id="messageAdapter" class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
    <property name="messageConverters">
        <list>
            <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter" >
            <property name="supportedMediaTypes">    
                <list>    
                    <value>application/json;charset=utf-8</value>    
               </list>    
            </property>  
            </bean>
        </list>
    </property>
</bean>

maven pom.xml

    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.9.6</version>
    </dependency>

Java 控制器

@RequestMapping(value = "/search.do", method = RequestMethod.GET, consumes = { "application/json" })
public @ResponseBody Results search(@RequestBody Map<String,Object> filters, HttpServletRequest request) {

0

你没有正确地获取JSON。

像这样做...

/*
 * Mapping for Demographics And Profiling Question Filter
 */
@RequestMapping (value = "/generalFilter")
public void ageFilteration(@RequestParam Map <String,String> filterParams,HttpServletRequest request,HttpServletResponse response) throws IOException
{
    //  System.out.println("Geographies in Controller :"+ filterParams.get("geographies"));
    List<FeasibilityBean> feasibilityList = feasibilityDao.getGeneralFeasibilityList(filterParams,request);
    //  System.out.println(" General Filter List Size:"+feasibilityList.size());
    response.getWriter().print(new Gson().toJsonTree(feasibilityList,new TypeToken<List<FeasibilityBean>>(){}.getType()));
}

}

Js代码

var ages='',ageCond='',genders='',genderCond='';

    $.ajax({
        type: "POST",
        url : url,
        data : {ages:ages,ageCond:ageCond,genders:genders,genderCond:genderCond},
        beforeSend: function() { 
            $(thisVar).find('i').addClass('fa-spin');
        },
        success : function(feasibilityJson){ 

        },
        error : function(data) {
            alert(data + "error");
        },
        complete:function(){  
            $(thisVar).find('i').removeClass('fa-spin');
        }
    }); 

或者你想将bean与json绑定....

https://dev59.com/PGEi5IYBdhLWcg3wJpcl#21689084 https://dev59.com/PGEi5IYBdhLWcg3wJpcl#37958883


0
    @RequestMapping(method = RequestMethod.POST)
    public HttpEntity<Resource<Customize>> customize(@RequestBody String customizeRequest) throws IOException {
       Map<String, String> map = mapper.readValue(customizeRequest, new TypeReference<Map<String,String>>(){});
       log.info("JSONX: " + customizeRequest);
       Long projectId_L = Long.parseLong(map.get("projectId"));
       [...]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接