Menu

Monday, June 28, 2021

[Java - Spring Boot] วิธีการสร้าง JSON response สำหรับทุก controller ใน Spring Boot
[Java - Spring Boot] How to Wrap JSON Response for All Controllers in Spring Boot

หลังจากเรากำหนด @RestController ที่เหนือ class ของ controller ทำให้ object ที่ return จาก controller นั้นจะถูกแปลงไปเป็น JSON response ให้โดยอัตโนมัติ

อย่างไรก็ตาม ถ้าหากเราต้องการสร้าง template ครอบ object ที่ return จาก controller ทุกๆ controller ก่อนที่จะส่งเป็น JSON response ออกไป เรามีขั้นตอนดังนี้

  1. สร้าง Class สำหรับ JSON response template
    package com.example.model.wrapper;
    
    import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
    import com.fasterxml.jackson.annotation.JsonInclude;
    import com.fasterxml.jackson.annotation.JsonProperty;
    import org.springframework.http.HttpStatus;
    
    @JsonIgnoreProperties(ignoreUnknown = true)
    @JsonInclude(JsonInclude.Include.NON_NULL)
    public class ResultWrapper<T> {
        @JsonProperty("code")
        private Integer code;
        @JsonProperty("status")
        private HttpStatus status;
        @JsonProperty("message")
        private String message;
        @JsonProperty("data")
        private T data = null;
    
    
        public Result(Integer code, HttpStatus status, String message) {
            this.code = code;
            this.status = status;
            this.message = message;
        }
    
        public ResultWrapper(Integer code, HttpStatus status, T data) {
            this.code = code;
            this.status = status;
            this.data = data;
        }
    }
    
  2. สร้าง class ที่เรียกใช้ ControllerAdvice และ ResponseBodyAdvice ดังนี้
    package com.example.controller.;
    import com.example.model.wrapper.ResultWrapper; import org.springframework.core.MethodParameter; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.server.ServerHttpRequest; import org.springframework.http.server.ServerHttpResponse; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice; import java.util.LinkedHashMap; @ControllerAdvice public class ResponseHandler implements ResponseBodyAdvice<Object> { @Override public boolean supports(MethodParameter methodParameter, Class> aClass) { // Skip methods in ExceptionHandler class Boolean isExceptionHandlerMethod = methodParameter.getDeclaringClass().getSimpleName().equals("ExceptionHandler"); return !isExceptionHandlerMethod; } @Override public Object beforeBodyWrite(Object body, MethodParameter methodParameter, MediaType mediaType, Class> aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) { // Convert error that is LinkedHashMap class too if(body instanceof LinkedHashMap){ LinkedHashMap map = (LinkedHashMap) body; if(map.containsKey("status") && !map.get("status").equals(200)){ HttpStatus status = HttpStatus.resolve((int) map.get("status")); return new ResultWrapper(status.value(), status, (String) map.get("error")); } } HttpStatus status = HttpStatus.OK; return new ResultWrapper(status.value(), status, body); } }
คำอธิบายเพิ่มเติม
  1. @ControllerAdvice - อนุญาตให้เรา apply เทคนิคใน class ข้างใต้มันกับทุกๆ controller ของเรา (อ่านเพิ่มเติมที่ ControllerAdvice)
  2. ResponseBodyAdvice - อนุญาตให้เราเปลี่ยนแปลง response ที่ได้จาก controller ก่อนที่มันจะถูกแปลงเป็น HttpResponse แล้วส่งออกไป (อ่านเพิ่มเติมที่ ResponseBodyAdvice)

No comments:

Post a Comment