關於使用fastjson統一序列化響應格式
摘要:其實很簡單的處理方式,只不夠優雅,或者說沒有找到fastjson為其提供便捷的處理方式。因此記錄下處理該問題的過程。
目標:將所有api請求,即響應為APPLICATION_JSON的內容做統一格式處理。 例如:@RestController 標註類方法放回值為List、 Map 或PO 類 增加響應欄位 status。
- 當成功響應List 時,返回 {"data":[],"status":true}
- 當成功響應非List時,
- String : {"msg":"str","status":true}
- Map: {"k1":"v1","status":true}
- PO: {"column1":"v1","status":true}
- 當業務不能如預期處理,即異常響應:{"msg":"異常理由","status":false}
1:業務預期失敗 在spring boot中配置HandlerExceptionResolver後,即可攔截處理所有異常,在此便可處理錯誤信息的json化。
@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.集合情況和String等非PO和非Map類型 ** 使用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()) {
// 數組
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.非集合情況,即PO 及Map 使用com.alibaba.fastjson.serializer.BeforeFilter
@Bean
public HttpMessageConverters fastJsonHttpMessageConverters() {
// 1、定義一個convert轉換消息的對象
FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter();
// 2、添加fastjson的配置信息
FastJsonConfig fastJsonConfig = new FastJsonConfig();
SerializerFeature[] serializerFeatures = new SerializerFeature[] {
// 輸出key是包含雙引號
// SerializerFeature.QuoteFieldNames,
// 是否輸出為null的欄位,若為null 則顯示該欄位
SerializerFeature.WriteMapNullValue,
// 數值欄位如果為null,則輸出為0
// SerializerFeature.WriteNullNumberAsZero,
// List欄位如果為null,輸出為[],而非null
SerializerFeature.WriteNullListAsEmpty,
// 字元類型欄位如果為null,輸出為"",而非null
// SerializerFeature.WriteNullStringAsEmpty,
// Boolean欄位如果為null,輸出為false,而非null
// SerializerFeature.WriteNullBooleanAsFalse,
// Date的日期轉換器
SerializerFeature.WriteDateUseDateFormat,
// 循環引用
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、在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、將convert添加到converters中
HttpMessageConverter<?> converter = fastConverter;
return new HttpMessageConverters(converter);
}
TAG:程序員小新人學習 |