自学内容网 自学内容网

记录jackson解析出错

Jackson 属性名大小写 Bug 记录

问题描述

在前后端交互过程中,前端传递的 JSON 字段名为驼峰风格(如 qTitle),后端 Java 实体类字段名也为驼峰(如 private String qTitle;)。
但在反序列化时,发现后端接收到的 qTitle 字段始终为 null,导致如 @NotBlank(message = "问卷标题不能为空") 校验失败。

现象

  • 前端请求体:
    {
      "qTitle": "2024年员工满意度调查问卷",
      ...
    }
    
  • 后端实体类:
    public class QuestionnaireCreateRequest {
        @NotBlank(message = "问卷标题不能为空")
        private String qTitle;
        // ...
    }
    
  • 实际后端接收到的 qTitle 字段为 null,触发校验异常。

排查过程

  1. 确认前后端字段名一致,均为驼峰。
  2. 查看 Jackson 源码,定位到 legacyManglePropertyName 方法:
     /**
      * Method called to figure out name of the property, given 
      * corresponding suggested name based on a method or field name.
      *
      * @param basename Name of accessor/mutator method, not including prefix
      *  ("get"/"is"/"set")
      */
     protected String legacyManglePropertyName(final String basename, final int offset)
     {
         final int end = basename.length();
         if (end == offset) { // empty name, nope
             return null;
         }
         char c = basename.charAt(offset);
         // 12-Oct-2020, tatu: Additional configurability; allow checking that
         //    base name is acceptable (currently just by checking first character)
         if (_baseNameValidator != null) {
             if (!_baseNameValidator.accept(c, basename, offset)) {
                 return null;
             }
         }
    
         // next check: is the first character upper case? If not, return as is
         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();
     }
    
  3. 分析得出:
    • 如果属性名第一个字母是小写,第二个字母是大写(如 qTitle),Jackson 会将整个属性名转为小写(qtitle)。
    • 这导致 JSON 里的 qTitle 和 Java 字段 qTitle 匹配不上。

解决方案

  1. 推荐:避免使用单字母+大写字母的属性名。
    • 例如,将 qTitle 改为 questionTitle
  2. 如必须使用,添加 @JsonProperty 注解:
    @JsonProperty("qTitle")
    private String qTitle;
    
  3. 确保 Jackson 配置为默认大小写敏感,命名策略为 LOWER_CAMEL_CASE
  4. 团队命名规范建议:
    • 尽量使用完整单词命名,避免单字母+大写字母的驼峰风格。

总结

本次 bug 的根本原因是 Jackson 对属性名的“遗留”处理逻辑,遇到小写字母后紧跟大写字母的属性名时,会将整个属性名转为小写,导致前后端字段无法正确映射。
建议统一命名规范,或使用 @JsonProperty 明确指定字段名,彻底规避此类问题。


原文地址:https://blog.csdn.net/zym1095839105/article/details/148635976

免责声明:本站文章内容转载自网络资源,如侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!