7

I am using Spring MVC with Controllers, my question is how do I return a JSON response which is different from the @ResponseBody object which is returned and convereted to a JSON to be returned.

To elaborate further, I have the object called "UserDetails" which has two fields called "name", "emailAddress"

@ResponseBody UserDetails

now the json returned will look like

{ name : "TheUsersName", emailAddress:"[email protected]" }

Is there any way I can modify the json before returning (ALL jsons in all methods across all controllers) where a "status" field will be added and the other json data will be under the "data" key in the json.

Also how do I return a json to the frontend when the java server from somewhere throws an exception, the json should have "status : false" and the exception name (atleast the status part though)

1

3 Answers 3

14

Create a response class:

public class Response<T> {
    T data;
    boolean status = true;

    public Response(T d) { data = d; }
}

Then return that from your controllers:

@ResponseBody public Response getUserDetails) {
    //...
    return new Response(userDetails);
}

For the exception you'll want to return an object like:

public class BadStatus {
    String errorMessage;
    boolean status = false;

    public BadStatus(String msg) { errorMessage = msg; }
}

@ExceptionHandler(Exception.class)
public BadStatus handleException(Exception ex, HttpServletRequest request) {
  return new BadStatus(ex.getMessage());
}
Sign up to request clarification or add additional context in comments.

1 Comment

See this thread for a more detailed answer: stackoverflow.com/questions/5641091/…
2

Yes. Return a model and a view instead.

public ModelMap getUserDetails() {
    UserDetails userDetails; // get this object from somewhere
    ModelMap map = new ModelMap()(;
    map.addAttribute("data", userDetails);
    map.addAttribute("success", true);
    return map;
}

To add the exception you'd do it the same way with a key and success = false.

3 Comments

I don't see what value ModelAndView adds here. Why not just return the ModelMap?
I am unsure of why I would want to use a ModelAndView however you gave me the idea of using a map (HashMap) which worked like a charm and gave me the desired output. However how do I do the same in a fail scenario? However any idea of a way to centralize this when for all controllers and all functions in the controllers?
@skaffman You're right. Brain fart from returning views as well. @milindaD ModelMap doesn't require keys but not much different. It implements Map.
2

An alternate solution (works with spring 3.1), which is less invasive

in your spring config :

<bean id="jacksonConverter"     class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter" />
<mvc:annotation-driven>
    <mvc:message-converters>
        <bean class="mypackage.MyMessageConverter"
            p:delegate-ref="jacksonConverter">
        </bean>
    </mvc:message-converters>
</mvc:annotation-driven>

The idea is to provide your own HttpMessageConverter that delegates to the provided jackson converter.

public class MyMessageConverter implements HttpMessageConverter<Object> {
// setters and delegating overrides ommitted for brevity
@Override
    public void write(Object t, MediaType contentType, HttpOutputMessage outputMessage) throws IOException,
            HttpMessageNotWritableException {
// t is whatever your @ResponseBody annotated methods return
        MyPojoWrapper response = new MyPojoWrapper(t);

        delegate.write(response, contentType, outputMessage);
    }
}

This way all your pojos are wrapped with some other json that you provide there.

For exceptions, the solution proposed by ericacm is the simplest way to go (remember to annotate the 'BadStatus' return type with @ResponseBody).

A caveat : your json-serialized BadStatus goes through MyMessageConverter too, so you will want to test for the object type in the overriden 'write' method, or have MyPojoWrapper handle that.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.