Standardizing API Response Structure with Custom Annotations in Spring Boot
This article explains how to design a unified JSON response format for backend services, define clear status‑code conventions, encapsulate results in a Result class, and use a custom @ResponseResult annotation together with a ResponseBodyAdvice interceptor to automatically wrap controller outputs, improving readability and error handling.
In modern micro‑service architectures the front‑end and back‑end communicate via HTTP APIs. The article first outlines a typical overall system diagram and stresses that the focus is on API interfaces rather than gateways, caches, or message queues.
Response format : The back‑end should return a JSON object with four fields – code (integer status code), message (description), data (payload), and an optional status indicator. Example:
{
// return status code
code: integer,
// return message description
message: string,
// return value
data: object
}Code status design : Instead of ad‑hoc codes, follow the HTTP status‑code philosophy. Common ranges can be defined, e.g., 1000‑1999 for parameter errors, 2000‑2999 for user errors, 3000‑3999 for interface exceptions. This makes it easy for front‑end developers to map errors to messages.
Message field : Provides a human‑readable description of the error, usually paired with the status code.
Data field : Holds the actual business data in JSON format; its structure varies per endpoint.
Result class : A wrapper class that contains the above fields and static factory methods such as Result.success(data) and Result.failure(code, message) to simplify controller code.
Controller improvements : By using the static methods, controller methods become concise. Example controller code is shown where an Order object is wrapped with Result.success(order) .
Elegant optimization : Adding static helper methods to Result reduces boilerplate and improves readability.
Custom annotation @ResponseResult : Mark controller classes or methods that need automatic response wrapping.
Interceptor : A request interceptor checks for the presence of @ResponseResult on the handler method and sets a flag.
ResponseBodyAdvice implementation : When the flag is set, the advice rewrites the original return value into a Result object. It also handles exceptions by converting them into the same JSON structure.
@ControllerAdvice
public class GlobalResponseAdvice implements ResponseBodyAdvice
{
// logic to wrap response or exception into Result
}The article notes that global exception handling can be added similarly, and suggests caching the annotation lookup to avoid reflection on every request.
Finally, the author summarizes the approach, encourages readers to extend it, and provides a brief discussion on possible further optimizations.
Top Architect
Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.