1、原因
”在SpringBoot默认序列化的情况下,Web请求的JSON字段包含首字母小写第二个字母大写的变量名无法解析(aName)“。这是由于SpringBoot默认采用Jackson作为序列化工具,Jackson要求遵循javabean的命名规则,第一个单词不能少于两个字符。
2、代码
Jackson的BeanUtil类下的legacyManglePropertyName方法。
protected static String legacyManglePropertyName(final String basename, final int offset) {
final int end = basename.length();
if (end == offset) { // empty name, nope
return null;
}
// next check: is the first character upper case? If not, return as is
char c = basename.charAt(offset);
char d = Character.toLowerCase(c);
if (c == d) {
return basename.substring(offset);
}
// otherwise, lower case initial chars. Common case first, just one char
StringBuilder sb = new StringBuilder(end - offset);
sb.append(d);
int i = offset+1;
for (; i < end; ++i) {
c = basename.charAt(i);
d = Character.toLowerCase(c);
if (c == d) {
sb.append(basename, i, end);
break;
}
sb.append(d);
}
return sb.toString();
}
可以看到最下方的StringBuilder就是最终获取的属性值,sb首先加入d("a",原offset为3时已转换小写),然后把偏移量向后+1。在第一次循环中的c和d分别是“N”和“n”。
这里有一个比较奇怪的判断:如果c == d,则直接拼接后续的字符串,跳出循环;否则,将小写字符拼接后,继续遍历。
第一次遍历后sb的值为“an”。
第二次遍历,由于c == d(“a”==“a”),所以直接拼接后续字符串。
得到sb的最终结果为“aname”。
3、结论
三个解决方案:
- 使用其他JSON序列化包替换Jackson的MessageConverter。
- 使用@JsonProperty("aname")注解类属性,指定错误反序列化后的属性名。
- 遵循JavaBean命名规范
参考文献: