About using fastjson to unify the serialization response format.

Keywords: JSON Spring

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.

  1. When responding to the List successfully, {"data":[],"status":true}
  2. When successfully responding to a non List,
  • String : {"msg":"str","status":true}
  • Map: {"k1":"v1","status":true}
  • PO: {"column1":"v1","status":true}
  1. 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);
	}

Posted by xadmin on Wed, 18 Dec 2019 11:35:03 -0800