Передача карты JSON в Spring MVC Controller

Я пытаюсь отправить 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 считывать JSON через параметр GET/POST.

Как передать JSON-представления объектов из клиентского AJAX-запроса на контроллер Spring в качестве параметра запроса и получить объект Java?

EDIT Добавление моей соответствующей конфигурации 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
}

Это действительно решает мою непосредственную проблему, но мне все же интересно узнать, как можно передать несколько объектов JSON через вызов AJAX.

Ответ 1

Это действительно решает мою непосредственную проблему, но мне все же интересно узнать, как можно передать несколько объектов JSON через вызов AJAX.

Лучший способ сделать это - иметь объект-оболочку, содержащий два (или несколько) объектов, которые вы хотите передать. Затем вы создаете свой объект 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;
}   

}

Ответ 2

Вы можете использовать библиотеку Джексона для преобразования из Json в Map.

@Веб-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 (например, jquery Ajax)

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

Это намного проще с Python Framework или Play! уффф

Ответ 3

Вы не получаете 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....

fooobar.com/questions/228207/... fooobar.com/questions/228207/...

Ответ 4

Я передал объект 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);
  }
}

Ответ 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"));
       [...]