Absrtact: in fact, it's a very simple way to deal with it. It's not elegant enough, or fast JSON has not been found to provide a convenient way to deal with it. So record the process of dealing with the problem.
Objective: all api requests, i.e. responses, are processed in a unified format for the content of application [JSON]. For example: the @ RestController annotation class method adds the response field status to the List, Map or PO class.
- When responding to the List successfully, {"data":[],"status":true}
- When successfully responding to a non List,
- String : {"msg":"str","status":true}
- Map: {"k1":"v1","status":true}
- PO: {"column1":"v1","status":true}
- When the business cannot be handled as expected, the exception response is: {"msg": "exception reason", "status":false}
1: business expectation fails After the HandlerExceptionResolver is configured in spring boot, all exceptions can be intercepted and handled, and the json of error information can be handled here.
@Component public class GlobalExceptionResolver implements HandlerExceptionResolver { @Override public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { response.setStatus(getStatusCodeValue()); response.setContentType(ContentType.APPLICATION_JSON.toString()); response.setCharacterEncoding(Charsets.UTF_8.toString()); ... } }
**2. Set status and String and other non PO and non Map types** Register special content interception with ControllerAdvice
@ControllerAdvice public class ResponseResultHandler implements ResponseBodyAdvice<Object> { @Override public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) { if( Collection.class.isAssignableFrom(returnType.getMethod().getReturnType()) || returnType.getMethod().getReturnType().isArray()){ return true; } } @Override public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) { if (Collection.class.isAssignableFrom(returnType.getMethod().getReturnType()) || returnType.getMethod().getReturnType().isArray()) { // array if (MediaType.TEXT_HTML.equals(selectedContentType) || MediaType.TEXT_PLAIN.equals(selectedContentType)) if (!Stream.of(returnType.getMethod().getAnnotations()).anyMatch(a -> { if (a instanceof RequestMapping) { return !Objs.isEmpty(((RequestMapping) a).produces()); } return false; })) { response.getHeaders() .setContentType(MediaType.parseMediaType(MediaType.APPLICATION_JSON_UTF8_VALUE)); return JSONObject.toJSONString(Pages.builder((Collection<?>) body)); } return Pages.builder((Collection<?>) body); } ... } }
3. Non set case, i.e. PO and Map Use com.alibaba.fastjson.serializer.BeforeFilter
@Bean public HttpMessageConverters fastJsonHttpMessageConverters() { // 1. Define a convert conversion message object FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter(); // 2. Add the configuration information of fastjson FastJsonConfig fastJsonConfig = new FastJsonConfig(); SerializerFeature[] serializerFeatures = new SerializerFeature[] { // The output key contains double quotes // SerializerFeature.QuoteFieldNames, // Whether to output a null field. If it is null, the field will be displayed SerializerFeature.WriteMapNullValue, // If the value field is null, the output is 0 // SerializerFeature.WriteNullNumberAsZero, // If the List field is null, the output is [], not null SerializerFeature.WriteNullListAsEmpty, // If the character type field is null, the output is' ', not null // SerializerFeature.WriteNullStringAsEmpty, // If the Boolean field is null, the output is false instead of null // SerializerFeature.WriteNullBooleanAsFalse, // Date Converter for date SerializerFeature.WriteDateUseDateFormat, // Circular reference SerializerFeature.DisableCircularReferenceDetect, }; fastJsonConfig.setSerializerFeatures(serializerFeatures); fastJsonConfig.setCharset(Charset.forName("UTF-8")); fastJsonConfig.setSerializeFilters(new BeforeFilter()BeforeFilter { private final ThreadLocal<Boolean> localTask=new ThreadLocal<>(); @Override public void writeBefore(Object object) { if (localTask.get() != null) return; writeKeyValue("status", true); localTask.set(true); } }); // 3. Add configuration information to convert fastConverter.setFastJsonConfig(fastJsonConfig); List<MediaType> fastMediaTypes = new ArrayList<>(); fastMediaTypes.add(MediaType.APPLICATION_JSON_UTF8); // fastMediaTypes.add(MediaType.TEXT_HTML); // fastMediaTypes.add(MediaType.TEXT_PLAIN); fastConverter.setSupportedMediaTypes(fastMediaTypes); // 4. Add convert to converters HttpMessageConverter<?> converter = fastConverter; return new HttpMessageConverters(converter); }