Reputation: 445
I am trying to figure out how I will manage to return a JSON output from a Controller. For the time being, I am returning my results and getting them with the use of freemarker view resolver. The code inside my controller is the following:
@RequestMapping(value = "query", method = RequestMethod.GET)
public ModelAndView search(
@RequestParam(required = true) String q
){
ModelAndView mv = new ModelAndView(getPartial("template"));
mv.addObject("terms",q.replace(","," "));
mv.addObject("results",getResultsForQuery(q));
return mv;
}
and the configuration for the freemarker:
<!-- freemarker config -->
<bean id="freemarkerConfig" class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
<property name="templateLoaderPath" value="/freemarker/"/>
<property name="freemarkerSettings">
<props>
<prop key="locale">en_US</prop>
</props>
</property>
</bean>
<bean class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">
<property name="order" value="1"/>
<property name="exposeSpringMacroHelpers" value="true"/>
<property name="cache" value="false"/>
<property name="suffix" value=".ftl"/>
<property name="contentType" value="text/html;charset=UTF-8"/>
</bean>
As far as I have understood so far, there are two ways of returning a JSON object, a)by modifying the controller and b)without modifying it by changing the configuration. Moreover, I have read about returning JSON throuh ResponseBody but not sure what should I change to configuration. Could anyone first of all, verify whether the above conclusions are valid or not, and second help me returning JSON from this GET method?
*UPDATE** If I use ResponseBody and configuration like this:
<!-- json config -->
<bean id="viewName" class="org.springframework.web.servlet.view.json.MappingJacksonJsonView" />
should I remove the freemarker confiuration?
Thank you in advance for your help.
Upvotes: 0
Views: 1437
Reputation: 921
Upvotes: 0
Reputation: 8154
There are several ways you can return JSON. My preferred way is to include the Jackson libs in your classpath, configure your Controller's handler method to return the object, and mark the return as @ResponseBody. Spring MVC will connect all the dots, serialize the response to JSON, and all will be good. You can even use annotations and/or direct code from Jackson to control how the serialization occurs.
The next way I would consider is to serialize to JSON myself, either with Jackson or some other lib, but you could also do this with a StringBuffer and brute force. To do so, change the return type from the above to String, leave the @ResponseBody on the return, and optionally drop the Jackson libs. In this case, you are responsible for generating the JSON. It is up to you to ensure it's well-formed, because whatever you return for the String will get returned to the browser directly. You will probably also want to change the Content-Type header to reflect you are returning JSON.
The next way would be to return either a ModelAndView or a View. I personally don't like this way, as it's a rather old way of doing Spring MVC. But, it's supported, so I will discuss. In this case, you would create either an instance of a JSON-enabled View object, or some other custom View, and return that (either directly or as part of a ModelAndView). I have used this method to return CSV files in which I want to optionally send the user to an error page if the CSV generation fails, which I can do since I can flop out the views conditionally. Not my favorite approach, however, as to me it requires quite a bit of extra coding on my part. I am lazy...sue me.
Option 4: Simply have a JSP/Thymeleaf/etc view that "looks" like JSON. JSPs don't necessarily have to produce HTML. It just needs to parse. One could, in theory, use JSTL and such to output something JSON-esque. I think this would be a sloppy way to do it, though.
There may be some other ways, but I think those are the top 4 I can think of. I think, given the fact that you will need to modify code anyhow, that the first option would be the one I would go with. Makes the code look nice a clean, and in my opinion, easier for people to understand what's happening.
Upvotes: 1
Reputation: 48287
You have a few options, depending on what you want to do.
The most flexible way would be to avoid @ResponseBody and stick to using Spring MVC's view system.
This would allow you to use the same controllers for XML, JSON, JasperReports, and HTML views.
For JSON, you should use the MappingJackson2JsonView, and make sure Jackson is in your classpath.
If you only want to return JSON, then the MappingJackson2JsonView view should be your only view. If you want to return multiple content types depending on the request, you should use the ContentNegotiatingViewResolver, with other views such as MarshallingView for XML or FreeMarkerViewResolver.
Upvotes: 0