场景
接口调用时,当参数首字母为大写时,json 反序列化成 javaBean 没有序列化成功。
测试现象
- 传值时参数名为小写字母开头
接收参数名是大写或小写开头都能收到 - 传值时参数名大写
接收参数名是大写或小写开头都不能收到
可能原因
和 javaBean的规范有关
可参考 https://www.cnblogs.com/sunTin/p/7172932.html
如果首字母大写,也是属性名直接用作 getter/setter 方法中 get/set
的后部分。例如属性名为Name,方法是getName/setName,这种是最糟糕的情况,会找不到属性出错,因为默认的属性名是name。
解决方案
一开始的解决方案是接口调用时直接用 JSONObject接收
@RequestMapping(value = "org/promote", method = RequestMethod.POST)
@ResponseBody
public Boolean promote(@RequestBody JSONObject jsonObject) {
TenantOrderParam tenantOrderParam = preHandle(jsonObject);
log.info("收到套餐升级请求:{}", tenantOrderParam);
return syncService.promote(tenantOrderParam);
}
然后把 JSONObject转成 string,把参数中首字母大写的参数转成小写开头,方法如下
private TenantOrderParam preHandle(JSONObject jsonObject){
String temp = jsonObject.toString();
temp = CommonUtils.jsonParamNameFirstOneConvert(temp,2);
return JSONObject.parseObject(temp,TenantOrderParam.class);
}
public static String jsonParamNameFirstOneConvert(String str, Integer rule) {
String splitRule0 = "", splitRule1 = ":", splitRule2 = ",\"", splitRule3 = "\"", splitRule4 = "{", splitRule5 = "[";
String[] split = str.split(splitRule1);
List<String> params = new ArrayList<>();
for (int i = 0; i < split.length; i++) {
if (i == (split.length - 1)) {
break;
}
String[] ss = split[i].split(splitRule2);
String result = ss[ss.length - 1].replace(splitRule3, splitRule0).replace(splitRule4, splitRule0).replace(splitRule5, splitRule0);
params.add(result);
}
for (String param : params) {
String newParam = null;
if (rule.equals(1)) {
newParam = toUpperCaseFirstOne(param);
} else {
newParam = toLowerCaseFirstOne(param);
}
str = str.replace(param, newParam);
}
return str;
}
/**
* 首字母转小写
*
* @param str 字符串
* @return 转换后的字符串
*/
private static String toLowerCaseFirstOne(String str) {
if (Character.isLowerCase(str.charAt(0))) {
return str;
} else {
return (new StringBuilder()).append(Character.toLowerCase(str.charAt(0))).append(str.substring(1)).toString();
}
}
/**
* 首字母转大写
*
* @param str 字符串
* @return 转换后的字符串
*/
private static String toUpperCaseFirstOne(String str) {
if (Character.isUpperCase(str.charAt(0))) {
return str;
} else {
return (new StringBuilder()).append(Character.toUpperCase(str.charAt(0))).append(str.substring(1)).toString();
}
}
后来发现可以更改springboot默认 json 转换工具,从 jackson 改成 fastJson。。。。。。问题居然解决了!!
在启动类中加入如下代码
@Bean
public HttpMessageConverters fastJsonHttpMessageConverters() {
FastJsonHttpMessageConverter4 fastConverter = new FastJsonHttpMessageConverter4();
FastJsonConfig fastJsonConfig = new FastJsonConfig();
fastJsonConfig.setSerializerFeatures(SerializerFeature.PrettyFormat);
fastConverter.setFastJsonConfig(fastJsonConfig);
return new HttpMessageConverters((HttpMessageConverter<?>) fastConverter);
}
经测试,无论首字母大写小写都能正确反序列化,fastJson牛逼!