JQuery, Spring MVC @RequestBody and JSON - making it work together
Solution 1
I'm pretty sure you only have to register MappingJacksonHttpMessageConverter
(the easiest way to do that is through <mvc:annotation-driven />
in XML or @EnableWebMvc
in Java)
See:
Here's a working example:
Maven POM
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion><groupId>test</groupId><artifactId>json</artifactId><packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version><name>json test</name>
<dependencies>
<dependency><!-- spring mvc -->
<groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>3.0.5.RELEASE</version>
</dependency>
<dependency><!-- jackson -->
<groupId>org.codehaus.jackson</groupId><artifactId>jackson-mapper-asl</artifactId><version>1.4.2</version>
</dependency>
</dependencies>
<build><plugins>
<!-- javac --><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version><configuration><source>1.6</source><target>1.6</target></configuration></plugin>
<!-- jetty --><plugin><groupId>org.mortbay.jetty</groupId><artifactId>jetty-maven-plugin</artifactId>
<version>7.4.0.v20110414</version></plugin>
</plugins></build>
</project>
in folder src/main/webapp/WEB-INF
web.xml
<web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
version="2.4">
<servlet><servlet-name>json</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>json</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
json-servlet.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<import resource="classpath:mvc-context.xml" />
</beans>
in folder src/main/resources:
mvc-context.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<mvc:annotation-driven />
<context:component-scan base-package="test.json" />
</beans>
In folder src/main/java/test/json
TestController.java
@Controller
@RequestMapping("/test")
public class TestController {
@RequestMapping(method = RequestMethod.POST, value = "math")
@ResponseBody
public Result math(@RequestBody final Request request) {
final Result result = new Result();
result.setAddition(request.getLeft() + request.getRight());
result.setSubtraction(request.getLeft() - request.getRight());
result.setMultiplication(request.getLeft() * request.getRight());
return result;
}
}
Request.java
public class Request implements Serializable {
private static final long serialVersionUID = 1513207428686438208L;
private int left;
private int right;
public int getLeft() {return left;}
public void setLeft(int left) {this.left = left;}
public int getRight() {return right;}
public void setRight(int right) {this.right = right;}
}
Result.java
public class Result implements Serializable {
private static final long serialVersionUID = -5054749880960511861L;
private int addition;
private int subtraction;
private int multiplication;
public int getAddition() { return addition; }
public void setAddition(int addition) { this.addition = addition; }
public int getSubtraction() { return subtraction; }
public void setSubtraction(int subtraction) { this.subtraction = subtraction; }
public int getMultiplication() { return multiplication; }
public void setMultiplication(int multiplication) { this.multiplication = multiplication; }
}
You can test this setup by executing mvn jetty:run
on the command line, and then sending a POST request:
URL: http://localhost:8080/test/math
mime type: application/json
post body: { "left": 13 , "right" : 7 }
I used the Poster Firefox plugin to do this.
Here's what the response looks like:
{"addition":20,"subtraction":6,"multiplication":91}
Solution 2
In Addition you also need to be sure that you have
<context:annotation-config/>
in your SPring configuration xml.
I also would recommend you to read this blog post. It helped me alot. Spring blog - Ajax Simplifications in Spring 3.0
Update:
just checked my working code where I have @RequestBody
working correctly.
I also have this bean in my config:
<bean id="jacksonMessageConverter" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"></bean>
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<list>
<ref bean="jacksonMessageConverter"/>
</list>
</property>
</bean>
May be it would be nice to see what Log4j
is saying. it usually gives more information and from my experience the @RequestBody
will fail if your request's content type is not Application/JSON
. You can run Fiddler 2 to test it, or even Mozilla Live HTTP headers plugin can help.
Solution 3
In addition to the answers here...
if you are using jquery on the client side, this worked for me:
Java:
@RequestMapping(value = "/ajax/search/sync")
public String sync(@RequestBody Foo json) {
Jquery (you need to include Douglas Crockford's json2.js to have the JSON.stringify function):
$.ajax({
type: "post",
url: "sync", //your valid url
contentType: "application/json", //this is required for spring 3 - ajax to work (at least for me)
data: JSON.stringify(jsonobject), //json object or array of json objects
success: function(result) {
//do nothing
},
error: function(){
alert('failure');
}
});
Solution 4
If you do not want to configure the message converters yourself, you can use either @EnableWebMvc or <mvc:annotation-driven />, add Jackson to the classpath and Spring will give you both JSON, XML (and a few other converters) by default. Additionally, you will get some other commonly used features for conversion, formatting and validation.
Comments
-
Eran Medan almost 2 years
I would like to have a bidirectional JSON to Java serialization
I'm using successfully the Java to JSON to JQuery path... (
@ResponseBody
) e.g.@RequestMapping(value={"/fooBar/{id}"}, method=RequestMethod.GET) public @ResponseBody FooBar getFooBar( @PathVariable String id, HttpServletResponse response , ModelMap model) { response.setContentType("application/json"); ... }
and In JQuery I use
$.getJSON('fooBar/1', function(data) { //do something });
this works well (e.g. annotations work already, thanks to all the answerers)
However, how do I do the reverse path: have JSON be serialized to a Java Object back using RequestBody?
no matter what I try, I can't get something like this to work:
@RequestMapping(value={"/fooBar/save"}, method=RequestMethod.POST) public String saveFooBar(@RequestBody FooBar fooBar, HttpServletResponse response , ModelMap model) { //This method is never called. (it does when I remove the RequestBody...) }
I have Jackson configured correctly (it serializes on the way out) and I have MVC set as annotations driven of course
How do I make it work? is it possible at all? or is Spring / JSON / JQuery is oneway (out)?
Update:
I changed this Jackson setting
<bean id="jsonHttpMessageConverter" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter" /> <!-- Bind the return value of the Rest service to the ResponseBody. --> <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"> <property name="messageConverters"> <util:list id="beanList"> <ref bean="jsonHttpMessageConverter" /> <!-- <ref bean="xmlMessageConverter" /> --> </util:list> </property> </bean>
To the (almost similiar one) suggested
<bean id="jacksonMessageConverter" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"></bean> <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"> <property name="messageConverters"> <list> <ref bean="jacksonMessageConverter" /> </list> </property> </bean>
And it seems to work! I don't know what exactly did the trick, but it works...
-
Bozho about 13 yearsor use
<mvc:annotation-driven>
I think. -
Eran Medan about 13 yearsI already have serialization OUT (ResponseBody, my problem is serialization IN (RequestBody)
-
Eran Medan about 13 yearsHave if of course, not the question again, I do have ResponseBody working, it's the RequestBody that doesn't work and I'm sure I'm missing something basic...
-
Eran Medan about 13 yearsMappingJacksonHttpMessageConverter is already registered, but it works for me only for ResponseBody, how do I make it work for RequestBody?
-
Eran Medan about 13 years@Danny, Thanks for the update, this is exactly what I have, and I used "application/json" as the content type, could it be that only very simple Beans can be used? e.g. only primitive types? maybe that's what I'm missing...
-
danny.lesnik about 13 years@Eran, Have you tried log4j, you will see serialization exception or error coming from controller.
-
Eran Medan about 13 yearsNo additional erros in log4j :( and I haev the same been configuration... Is there a working sample somewhere I can download and debug the differences?
-
Eran Medan about 13 yearsNo exception in log4j, I'm close to giving up... is there a working sample out there I can start from? (a simple Response/Request Body + JSON / JQuery test?)
-
Eran Medan about 13 yearsI used your config and replaced the almost identical one I had, I really don't know what small change did the trick, but it did... so THANKS
-
Sean Patrick Floyd about 13 years@Eran I know you have solved your problem in the meantime, but I have now added a working example to my answer
-
kamaci over 12 years@Eran Medan, you say you changed configuration of xml file and it worked however this answer doesn't include anything like that. Which one to follow?
-
Eran Medan over 12 years@kamaci - see my update - the change that made it work was so small it's hardly noticable, you can see the working solution both in this answer (on which we are commenting) or in my update.
-
Stuart Blair over 12 years@SeanPatrickFloyd Wonderful.That's really clear. That said, I noticed a slight problem which surfaced when I tried this. The post body in the example is quoted as { "left": 13 ; "right" : 7 } which isn't legal JSON. I was getting 400 bad request codes when I tried it. Then I noticed that there was a semi-colon in there which isn't part of the JSON syntax. I found success by posting the following through curl -
curl -v -H "Content-Type: application/json" -X POST -d "{\"left\":13,\"right\":7}" http://localhost:8080/test/math
-
jackyesind almost 11 years@SeanPatrickFloyd if i don't have pojo means what should i do for example
math(@RequestBody final Request request)
you have Request java but i don't have class for json at that situation what i do? stackoverflow.com/questions/18102452/… -
egervari over 10 yearsThis will work because you're doing a POST and original poster was using GET.
-
Archit over 8 yearsHello Guys please suggest the solution for the same. I have tried but not able to solve. The same configuration I did for 2 other projects it worked but for the current project it is not working.
-
Sean Patrick Floyd over 8 years@Archit please ask a separate question and post your code
-
Dipanshu Verma almost 7 yearsDude thanks, for this brilliant piece of advice, Totally Loved it
-
user3198603 over 6 years@SeanPatrickFloyd can you please have a look at stackoverflow.com/questions/46632680/… ?