Home > Mobile >  Normalize response body in spring boot
Normalize response body in spring boot

Time:05-24

I do have some entity class (code without annotations for simplified example)

class User {
   public String id;
   public String name;
}

Now I want to output this via an API, but I want to structure my response in a special format, like

{
  "data": {
            "id": 1,
            "name": "mars3142"
          }, // user object or another entity or list...
  "meta": ...,
  "error": ...
}

The meta and/or error data should only be visible in special situations (like RuntimeExceptions). Where is the best place to transform my entity results into the normalized response? Do I need to write a filter for that? Does anybody has a sample code for that?

CodePudding user response:

I would suggest to implement something like following

public abstract class BaseResponse {
     //Meta data //Consider defining fields here needed for Happy path and Error responses
     //Contains common fields Ex. Tracking fields like correlationId, RequestId
     }

     public class ErrorResponse extends BaseResponse {
     //Error Fields
    }

    public class Response extends ErrorResponse {
    //Entity Object in your case
    }

I guess you can build your response like setting response from DAO to above suggested Structure in controller layer. For Error responses (In case of Runtime Exceptions), they're standardly build and retuned in @GlobalExceptionalHandler or other. Some patterns of exception handling are explained here https://www.baeldung.com/exception-handling-for-rest-with-spring

CodePudding user response:

Regarding your 2 questions:

  1. Design: The proper place for this response-mapping depends on the scope (all responses or just some) and existing components in your application's response layer.

  2. Patterns and Web-Framework concepts: I would not use the response-filters or -interceptors of your web-framework. Those should be used for cross-cutting concerns, or for chained processes (e.g. security, authorization, enrichment, sanitation).

Instead I would use the web-frameworks concepts and components that are responsible for response-representations, like ResponseEntity (HTTP-response representation, ControllerAdvice (error-handling), HttpMessageConverter.


There are 3 ways you could "wrap" your objects into uniform JSON-response models:

  1. Annotate class with the custom @JsonRootName as data and in special cases add meta and/or error attributes (through e.g. embedding into a wrapper or using a mixin)

  2. A JSON custom serializer that could extend from BeanSerializer which wraps this and any class uniformly in your given outer structure

  3. Modify Spring's MappingJackson2HttpMessageConverter to wrap any returned response object into the predefined JSON-structure

You could iterate from the simplest (1.) to the most complex (3.). Some iteration code (like 2.) can be reused in the next (3.).

1. Use a Wrapper Class

The first is rather a simple start where you can implement the "normalization" within controller-methods. You could for example put the object (serialized as data) into the "empty" meta-structure (wrapper-class) with an empty JsonNode, and meta or error properties.

2. Define a Custom Serializer

The second is pretty flexible and can be tested well in isolation (not even depending on Spring). It would allow to implement the complete object-wrapping in one place.

3. Customize Spring's HTTP Message Converter

The third is similar to the second but requires some knowledge about Spring's message-converters and allows you to transform each response-object to a specific JSON-response using Jackson's ObjectMapper.


Sample code can be found online, e.g. at Baeldung's Jackson or Spring tutorials, Springframework Guru articles.

  • Related