一、问题描述
近期项目开发过程中,项目使用的是前后端分离架构,前端使用ANT DESIGN VUE,后端采用SpringBoot+Mybatis,数据库使用PG。如果前端定义的VUE变量为空串,后端用实体接收后,保存到数据库中该变量的字段会为空串,而不是NULL,从而出现后端服务在发起数据库查询时,用IS NULL条件无法过滤出来字段为空的数据记录问题。
二、解决思路
针对上述提到的问题,有两种方案:
1、修改前端上送的所有页面代码,初始化变量时,将空串‘’全部替换成NULL
–修改的地方比较多,并且不能确保服务接口类的请求有出现空串,不建议使用
2、修改后端代码,在应用请求接收变量映射(将JSON字符串转成JAVA实体)处,统一将空串‘’替换成NULL
–修改地方比较少,可做到统一控制,兼容前端界面和接口请求,建议使用该方案
现行项目使用的SpringBoot框架,针对JSON的解析,将Jakson解析统一替换成FastJson,(解决jackson 解析的字段中有单个字母作为驼峰单词的, 单个字母后面的大写字母会默认取小写的, 而不是原样取值的问题如”wWorkDays”字段,使用jackson解析成JSON字符串时,会变成wworkDays,以致原样字段无法正确取值和传送),因此要实现对字符串变量做个性化处理,因此考虑在Fastjson的的反序列化逻辑中添加此处理逻辑,方案如下:
fastJsonConfig.getParserConfig().putDeserializer(String.class, new ObjectDeserializer() {@Overridepublic T deserialze(DefaultJSONParser parser, Type type, Object fieldName) {if (String.class.equals(type)) {String fieldValue = (String) parser.parse(fieldName);if (StrUtil.isBlank(fieldValue)) {fieldValue = null;}return (T) fieldValue;}return (T) parser.parse(fieldName);}
最终代码如下:
/** * 将SpringBoot的Jakson解析统一替换成FastJson * 以解决jackson 解析的字段中有单个字母作为驼峰单词的, 单个字母后面的大写字母会默认取小写的, 而不是原样取值的问题 * 如”wWorkDays”字段,使用jackson解析成JSON字符串时,会变成wworkDays,以致原样字段无法正确取值和传送 * 使用FastJson可解决该问题 * * @return */@Beanpublic HttpMessageConverters fastJsonHttpMessageConverters() {FastJsonHttpMessageConverter fastJsonHttpMessageConverter = new FastJsonHttpMessageConverter();fastJsonHttpMessageConverter.setSupportedMediaTypes(getSupportedMediaTypes());fastJsonHttpMessageConverter.setDefaultCharset(StandardCharsets.UTF_8);FastJsonConfig fastJsonConfig = new FastJsonConfig();fastJsonConfig.setDateFormat(“yyyy-MM-dd’T’HH:mm:ss.SSSXXX”);//全局转化成带时区的时间,例如,2021-09-28T09:28:05.000+08:00fastJsonConfig.setSerializerFeatures(SerializerFeature.DisableCircularReferenceDetect, //禁用循环引用SerializerFeature.IgnoreNonFieldGetter,//忽略NULL字段SerializerFeature.WriteDateUseDateFormat//使用统一的时间格式);// 对String变量反序列化进行定制处理,如果字符串为空串,则转为NULL// 注:由于前端定义的字符为空串,发送到后台保存到数据库会保存为空串,在PG数据库和MYSQL数据库查询时用,isNULL无法过滤出来记录fastJsonConfig.getParserConfig().putDeserializer(String.class, new ObjectDeserializer() {@Overridepublic T deserialze(DefaultJSONParser parser, Type type, Object fieldName) {if (String.class.equals(type)) {String fieldValue = (String) parser.parse(fieldName);if (StrUtil.isBlank(fieldValue)) {fieldValue = null;}return (T) fieldValue;}return (T) parser.parse(fieldName);}@Overridepublic int getFastMatchToken() {return 0;}});fastJsonHttpMessageConverter.setFastJsonConfig(fastJsonConfig);return new HttpMessageConverters(new StringHttpMessageConverter(StandardCharsets.UTF_8), fastJsonHttpMessageConverter);}/** * 支持的文档类型 * * @return */private List getSupportedMediaTypes() {List supportedMediaTypes = new ArrayList();supportedMediaTypes.add(MediaType.APPLICATION_JSON_UTF8);supportedMediaTypes.add(MediaType.APPLICATION_JSON);return supportedMediaTypes;}
三、问题总结
我们开发人员在碰到问题时头脑应该保持冷静,从了解原理出发,只要解决思路对,总会找到正确的解决之道。