SpringBoot类属性”第二个字母大写“反序列化问题

发布于:2024-05-23 ⋅ 阅读:(140) ⋅ 点赞:(0)

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命名规范

参考文献:

SpringBoot类属性”第二个字母大写“反序列化问题 - 知乎 (zhihu.com)


网站公告

今日签到

点亮在社区的每一天
去签到