一. 描述
1. 在springboot项目中用了 HttpMessageConverters 替换 MappingJackson2HttpMessageConverter
/** jackson替换为fastjson */
@Bean
public HttpMessageConverters fastJsonHttpMessageConverters() {
FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter();
FastJsonConfig fastJsonConfig = new FastJsonConfig();
fastJsonConfig.setSerializerFeatures(SerializerFeature.PrettyFormat,
SerializerFeature.DisableCircularReferenceDetect, SerializerFeature.WriteMapNullValue,
SerializerFeature.WriteDateUseDateFormat);
converter.setSupportedMediaTypes(setMediaType());
converter.setFastJsonConfig(fastJsonConfig);
return new HttpMessageConverters(converter);
}
/**
* 修改自定义消息转换器
* @param converters 消息转换器列表
*/
public List<MediaType> setMediaType() {
List<MediaType> supportedMediaTypes = new ArrayList<>();
supportedMediaTypes.add(MediaType.APPLICATION_JSON);
supportedMediaTypes.add(MediaType.APPLICATION_JSON_UTF8);
supportedMediaTypes.add(MediaType.APPLICATION_ATOM_XML);
supportedMediaTypes.add(MediaType.APPLICATION_FORM_URLENCODED);
supportedMediaTypes.add(MediaType.APPLICATION_OCTET_STREAM);
supportedMediaTypes.add(MediaType.APPLICATION_PDF);
supportedMediaTypes.add(MediaType.APPLICATION_RSS_XML);
supportedMediaTypes.add(MediaType.APPLICATION_XHTML_XML);
supportedMediaTypes.add(MediaType.APPLICATION_XML);
supportedMediaTypes.add(MediaType.IMAGE_GIF);
supportedMediaTypes.add(MediaType.IMAGE_JPEG);
supportedMediaTypes.add(MediaType.IMAGE_PNG);
supportedMediaTypes.add(MediaType.TEXT_EVENT_STREAM);
supportedMediaTypes.add(MediaType.TEXT_HTML);
supportedMediaTypes.add(MediaType.TEXT_MARKDOWN);
supportedMediaTypes.add(MediaType.TEXT_PLAIN);
supportedMediaTypes.add(MediaType.TEXT_XML);
return supportedMediaTypes;
}
2. 在controller 用 string介绍 json 值
出现了两个现象: 1--里面的值的顺序变了, 和json里面的顺序不一致了
2--里面的null 的值消失
二.原因
1. 通过断点, 发现在FastJsonHttpMessageConverter 中 转化string的方法
其中的反序列化是和 Feature 相关
2. 在 JSONObject 对象中是包含 null 的值
在用 String 接受时, 调用 JSONObject 的 JSON.toString() 方法, null 就不存在了
序列化的 SerializerFeature 支持
三.解决方法
1. 解决序列化的问题, 有两种
1. 使用 request 获取 body, 得到原始的字符串
public String getOriginalBody(HttpServletRequest request, String content) {
BufferedReader bufferedReader = null;
try {
if (request == null) {
return content;
} else if (request instanceof RequestWrapper) {
RequestWrapper requestWrapper = (RequestWrapper) request;
return requestWrapper.getBody();
} else {
StringBuilder builder = new StringBuilder();
bufferedReader = null;
InputStream inputStream = request.getInputStream();
if (inputStream != null) {
bufferedReader = new BufferedReader(new InputStreamReader(inputStream, Charset.forName("UTF-8")));
char[] charBuffer = new char[128];
int bytesRead = -1;
while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
builder.append(charBuffer, 0, bytesRead);
}
} else {
builder.append("");
}
return builder.toString();
}
} catch (Exception e) {
log.info("getOriginalBody valued, Exception:", e);
} finally {
if (bufferedReader != null) {
try {
bufferedReader.close();
} catch (Exception ex) {
log.info("getOriginalBody bufferedReader, Exception:", ex);
}
}
}
return content;
}
2. 在 FastJsonHttpMessageConverter 中指定 read的策略,反序列化的方式
fastJsonConfig.setFeatures(Feature.OrderedField);
2. 解决 string 中不包含 null 的问题
用 JSONObject 代替 String 获取 @RequestBody 中的内容, JSONObject 含有 null 的值, 不能使用 toString(), 默认不包含 null 的值, 需要自己填充 toJSONString 的 SerializerFeature
@RequestMapping(value = "/{path}/test", method = { RequestMethod.POST })
public Object test(@PathVariable("path") String path, @RequestParam("sign") String sign,
@RequestBody JSONObject json, HttpServletRequest request) {
String content = JSONObject.toJSONString(json, SerializerFeature.WriteMapNullValue);
return content;
}
四.fastjson的序列化反序列化
fastjson中SerializerFeature的用法及中文注解 参考: https://blog.csdn.net/xinyuan_java/article/details/102699378
fastjson中Feature的用法及中文注解 参考: https://blog.csdn.net/xinyuan_java/article/details/102699418
fastjson 提供了很多 对象、字符串 之间的转化策略, 效率也很高