Search code examples
jsonrestjacksonresteasy

How to decorate the json response with Resteasy


I am implementing a restfull service with Resteasy that will be consumed by a Extjs client, and i want to decorate the json object retrieved in the http response with some more attributes without using a wrapper class with additional attributes in the service method or overriding JacksonJsonProvider
Example:

raw object:

{
   "id":"1",
   "name":"Diego"
}

decorated object:

{
   "success":"true",
   "root":{
             "id":"1",
             "name":"Diego"
          }
}

I found JAXB Decorators but i could not implement a decorator for json type.

I tried to replace the entity that will be serialized with a wrapper using Interceptors but it doesn't work if a replace the entity which is a Collection.

Any suggestions?


Solution

  • You could write an Interceptor that wraps your JSON response before it is passed to the client. Here is an example code:

    1. Define custom HTTPServletResponseWrapper

      public class MyResponseWrapper extends HttpServletResponseWrapper {
          private ByteArrayOutputStream byteStream;
      
          public MyResponseWrapper(HttpServletResponse response, ByteArrayOutputStream byteStream) {
              super(response);
              this.byteStream = byteStream;
          }
      
          @Override
          public ServletOutputStream getOutputStream() throws IOException {
              return new ServletOutputStream() {
                  @Override
                  public void write(int b) throws IOException {
                      byteStream.write(b);
                  }
              };
          }
          @Override
          public PrintWriter getWriter() throws IOException {
              return new PrintWriter(byteStream);
          }
      }
      
    2. Define filter class:

      @WebFilter("/rest/*")
      public class JSONResponseFilter implements Filter {
      
          private final String JSON_RESPONSE = " { \"success\":\"true\", \"root\": ";
          private final String JSON_RESPONSE_CLOSE = "}";
      
          /* .. */
      
          @Override
          public void doFilter(ServletRequest request, ServletResponse response,
                  FilterChain chain) throws IOException, ServletException {
      
              // capture result in byteStream by using custom responseWrapper
              final HttpServletResponse httpResponse = (HttpServletResponse) response;
              final ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
              HttpServletResponseWrapper responseWrapper = new MyResponseWrapper(httpResponse, byteStream);
      
              // do normal processing but capture results in "byteStream"
              chain.doFilter(request, responseWrapper);
      
              // finally, wrap response with custom JSON
            // you can do fancier stuff here, but you get the idea
              out.write(JSON_RESPONSE.getBytes());
              out.write(byteStream.toByteArray());
              out.write(JSON_RESPONSE_CLOSE.getBytes());
          }
      }