Return JSON from MVC Controller - json

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.

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.

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.

create an instance of MappingJackson2JsonView
set view as above instance for the returned ModelAndView

Related

Jackson JSON provider for cxf:rsServer

I'm implementing a REST service using Camel's cxfrs component. Various examples I've seen around the inets say I can get the service to return a JSON serialization of the object in question using a cxf:providers tag, like so
<cxf:rsServer id="rsServer" address="${CXFserver}${service}" serviceClass="org.trinityhealth.esb.PersonService"
loggingFeatureEnabled="true" loggingSizeLimit="20">
<cxf:providers>
<bean id="jsonHandler" class="com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider" />
</cxf:providers>
</cxf:rsServer>
This compiles and deploys just fine. But no matter what variant of this config I try, the service responds with "No message body writer has been found for response class Person". The Person class has a "#XmlRootElement(name = "Person")" annotation in it, which I guess is great if I wanted XML produced. But I don't - I want JSON. Jackson has a ton of annotations, do I need to add one to the Person class to get my service to realize I want the class serialized by the Jackson writer?
I don't know Camel that well, but typically Jackson does NOT require root annotation, unlike JAXB (partly since JSON structure does not require name for root type), so it seems unlikely you would such annotation.
I am guessing that rather the registration does not succeed for some reason.

How converts list objects to JSON in gvnix

Hi I´m developing new controllers over GVNIX development tool but I don´t understand how it is transforming object list to JSON.
I have seen in the GEO example, the entities list are working with DataTables and the ajax filter it´s working with JSON. The database access are in BatchService that returns object list, but I havent found where the controller get´s this list and returns the JSON.
Can anybody help me to understand how it´s working ?
Thanks
The conversion is handle by Spring Web MVC based on #RequestMapping and #ResponseBody annotations value through Jaskson Library. (This post talk about it)
In addition, as standard Spring MVC Jackson converter doesn't use the ApplicationConversionService Bean, gvNIX includes a custom converter that uses this bean to serialize and bind some object (as Spring do in standard POST request). You can found this configuration in webmvc-config.xml file:
<bean class="org.gvnix.web.json.Jackson2RequestMappingHandlerAdapter"
id="dataBinderRequestMappingHandlerAdapter" p:order="1">
<property name="objectMapper">
<bean class="org.gvnix.web.json.ConversionServiceObjectMapper"/>
</property>
</bean>
Note: Jackson2RequestMappingHandlerAdapter only handles request which #RequestMapping propierties produces and consumes is set to application/json
Good luck!

Spring 3.1 custom JSON converters

Im using Spring MVC 3.1 which by default uses Jackson for JSON-Java conversions.
I need to create custom conversions for the following:
java.util.List (for all sorts of different types).
Enums to strings
java.util.Calendar
I have encountered a few different approaches for creating my custom converters:
As described here more or less, create a custom ObjectMapper:
public class CustomObjectMapper extends ObjectMapper...
Then adding MappingJacksonHttpMessageConverter to my servlet-context and register it with my custom ObjectMapper:
Then i guess I need to have some specific implementations in my custom objectMapper (how should it look like?).
A second approach talks about extending FormattingConversionServiceFactoryBean and create my own converters (a class that implements org.springframework.core.convert.converter.Converter) as described here.
UPDATE 1:
Another approach I have seen is to subcalss MappingJacksonHttpMessageConverter and override getJavaType method, as described here. To do this I will have to add my custom converter to the list of converters:
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<list>
<bean class="com.yl.app.CustomMappingJacksonHttpMessageConverter">
</list>
</property>
Which approach is the recommended one? Are these the only ones, is there a better way of doing it?
UPDATE 2:
I still don't get it. In practice, suppose I have class A and class B.
Class A holds a list of B:
public class A {
public List<B> list;
}
I would like to return an object of type A to my client. What should I do in my server besides adding the #ResponseBody annotation (which is not enough in this case as far as I get it)?
Both approaches serve different purposes:
The first approach that you have outlined is to customize Jackson ObjectMapper - say for eg, to show the date in a different format in the json or to register a custom serializer to handle mapping a class to a json a little differently.
The second approach is to register converters - to transform one object to another, say for eg, to convert a String request parameter from the UI to an object or say if you get the entity id of a field and want to convert it to an entity.
So both have their place, to customize Jackson you would use the first approach, to create custom converters you would use the second approach.
Update:
Based on the new information that you have provided, I think what you are looking for is actually a HttpMessageConverter not a Converter.
When you say you want to return an object of type A to your client, you would serialize it some way over the wire - json or xml typically, but potentially other formats also - if you are going to convert it to json then you essentially customize ObjectMapper underlying MappingJacksonHttpMessageConverter(with Jackson 1.x) or MappingJackson2HttpMessageConverter(with Jackson2.x) you would typically do this:
<mvc:annotation-driven conversion-service="conversionService">
<mvc:message-converters register-defaults="true">
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="objectMapper">
<bean class="org.bk.lmt.web.spring.CustomObjectMapper"/>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
and in the Custom Object Mapper, register the appropriate serializers/deserializers IF you want to customize the Json representation.
Similarly with XML, you would typically not write your own converter(Jaxb2RootElementHttpMessageConverter), but use XmlJavaAdapters to customize how some of the elements are serialized.
If you have some new serialization format (not xml, json), then yes, you can attempt writing a HttpMessageConverter from scratch.
After trying it myself, non of the listed approaches is required. Jackson (as is) is capable of handling nested Collections just fine, no customization required.

Spring Restful, Post multiple formats like json/xml/domain object into same action

I am writing a Spring Restful webservices application using Spring MVC. I have used content negotiating viewer to respond multiple data formats for eg. If some one requests a URL with .xml extension an XML will be sent in response body similarly if someone requests with an .json extension, an json will be sent in response body.
Now, I want the same process inwards, say if some body wants to post a Json or xml or a simple post from a webpage form using post method to same action, it should be able to handle all these.
This way i will be able to write a Web Service+Web Application in a single Spring MVC+Restful Application.
Thanks in advance for the help :)
You can use headers attribute of #RequestMapping annotation.
#RequestMapping(value = "/pets", method = RequestMethod.POST, headers="content-type=text/*")
to narrow content-type of requests your method is going to serve.
edit:
If you want to sent different content type in request body, then the only thing you need to do is to define MessageConverter (I assume you already did that) and annotate your method parameter with
#RequestBody
Spring should deserialize the body of your request using the MessageConverter you defined.
So assuming you have something like:
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<util:list>
<bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"/>
</util:list>
</property>
</bean>
<bean id="contentNegotiatingViewResolver" class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<property name="mediaTypes">
<util:map>
<entry key="json" value="application/json"/>
</util:map>
</property>
<property name="defaultViews">
<util:list>
<bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView"/>
</util:list>
</property>
</bean>
in your spring context.
Annotating your method like this:
#RequestMapping(method=PUT, value="/user/{user_id}")
public void putUser(#RequestBody User user, #PathVariable int user_id) {
...
}
should do the job.
You don't have to do anything. You register converts and they will in turn tell "spring" what Content-types they can handle. XStream registers application/xml and text/xml (perhaps more), jackson registers application/json and so on.
It's all available at http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/mvc.html#mvc-ann-responsebody
I also don't like the filename-standard, I prefer to leave that to the same converter. In that case it will look at the Accept-header. If you want json, set Accepts: application/json.

spring prefixjson with responsebody

when controller method return is #responsebody , even if i put
<bean
class="org.springframework.web.servlet.view.json.MappingJacksonJsonView">
<property name="prefixJson" value="true" />
</bean>
there will no && {} insert at the front of json data. anyone knows what is reason?
JSON in #RequestBody/#ResponseBody is handled by MappingJacksonHttpMessageConverter which is configured in AnnotationMethodHandlerAdapter.messageConverters.
The easy way to configure it without interference with other features is to create a BeanPostProcessor to intercept creation of AnnotationMethodHandlerAdapter, see, for example, here.