【问题标题】:Passing JSON Map into Spring MVC Controller将 JSON Map 传递给 Spring MVC 控制器
【发布时间】:2013-03-19 01:36:40
【问题描述】:

我正在尝试将 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
}

这将正确响应请求,但我意识到地图是空的。通过后来的实验,我发现任何对象(不仅仅是 HashMap)都会被实例化,但不会填写任何字段。我的类路径中确实有 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 吗?
  • 作为表单、ajax 请求的一部分,您如何发布数据?
  • 查看@RequestBody 注释。
  • @DeividiCavarzan 我的上下文中确实有 MappingJacksonJsonView。我将此数据作为 AJAX 请求发送。我已经尝试将它作为 GET 和 POST 来实现,效果相同。
  • 查看这个问题/答案:stackoverflow.com/questions/12475911/…

标签: java json spring spring-mvc


【解决方案1】:

这确实解决了我的直接问题,但我仍然很好奇您如何通过 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 修复了它!
【解决方案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>

@控制器

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

@Request(例如 jquery Ajax)

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

使用 Python 框架或 Play 更容易!呵呵

【讨论】:

  • Jackson 1.9.x 处于维护模式;我建议使用 Jackson 2.3.x。
【解决方案3】:

我已使用以下代码将 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是什么。
  • 按照建议编辑解决方案
【解决方案4】:

您没有正确获取 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');
        }
    }); 

或者你想用json绑定bean....

https://stackoverflow.com/a/21689084/5150781 https://stackoverflow.com/a/37958883/5150781

【讨论】:

    【解决方案5】:
        @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"));
           [...]
    

    【讨论】:

      【解决方案6】:

      作为@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>
      

      mavenpom.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) {
      

      【讨论】:

        猜你喜欢
        • 2020-08-23
        • 1970-01-01
        • 2014-03-17
        • 2014-04-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多