当前位置: 首页 > news >正文

JavaBean中首字母小写第二个字母大写属性转换异常详解

例如:将cAlertFormula 转换为 calertFormula

概述这是由 JavaBean 规范定义的命名约定所导致的,Lombok 作为一个严格遵守该规范的工具,正是按照这个约定来生成 getter/setter 方法的。

下面进行详细分解:

1. JavaBean 规范的核心规则

JavaBean 规范规定,getter 和 setter 方法的命名必须遵循以下模式:

  • Getterget + <CapitalizedFieldName>

  • Setterset + <CapitalizedFieldName>

关键点在于 <CapitalizedFieldName> 是如何从字段名 fieldName 转换而来的。

2. 针对首字母小写、第二个字母非大写的字段(绝大多数情况)

对于像 name 这样的字段:

  1. 字段名: name

  2. 首字母大写: Name

  3. 加上前缀: getName()setName()

这个过程很直观。

3. 针对首字母小写、但第二个字母大写的字段

对于字段 cAlertFormula,规则变得特殊。为了处理像 cAlertFormulaxAxisuRL 这样的字段,规范有一个特殊规定:

当字段名的前两个字母中,第一个是小写,第二个是大写时,首字母在转换为方法名时不应被大写。

这个规则的目的是为了保留那些实际上是首字母缩略词的字段的预期大小写。

让我们应用这个规则:

  1. 字段名: cAlertFormula

  2. 分析前两个字符: c (小写) + A (大写)。这符合上述特殊规则。

  3. 因此,首字母 c 保持小写,不转换为大写。

  4. 生成的方法名就是: getcAlertFormula()setcAlertFormula()

如果按照普通规则(错误地)处理,会得到 getCAlertFormula(),这会将首字母缩略词 “c” (可能代表 “critical”) 错误地转换为 “C”,改变了其含义。

4. Lombok 的角色

Lombok 的 @Getter 和 @Setter 注解的唯一工作就是根据 JavaBean 规范 生成正确格式的方法名。它非常严格地遵守这个规范,因此它会为 cAlertFormula 字段生成 getcAlertFormula() 和 setcAlertFormula() 方法。

5. Jackson 的默认行为(序列化原理)

默认情况下,Jackson 通过调用对象的 getter 方法 来发现要序列化的属性。当它看到一个方法叫 getcAlertFormula(),它会:

  1. 移除标准前缀
    Jackson 检测到方法名以 get 开头,于是移除这三个字母。

    • 结果: cAlertFormula

  2. 解耦首字母缩略词(关键步骤)
    这是最微妙且容易出错的一步。Jackson 的默认属性名推导逻辑(在 BeanUtil 类中)有一条特殊规则来处理首字母小写但第二个字母大写的字段(如 cAlertxAxisuRL)。

    • 规则: 如果剩余字符串(cAlertFormula)的前两个字符符合“小写字母后紧跟大写字母”的模式(即 cA),推导逻辑会尝试将这两个字符视为一个解耦的单位

    • 操作: 它将第一个字符(c)保持小写,然后将后续的所有连续大写字母转换为小写,直到遇到一个小写字母为止。

    • 应用规则:

      • 前两个字符: c (小写) + A (大写) -> 触发规则。

      • 将 A 转换为 a

      • 现在字符串变为 calertFormula

      • 下一个字符是 l (小写),规则停止应用。

  3. 首字母小写化(形式上的步骤)
    经过上一步的解耦操作后,字符串现在已经是 calertFormula。理论上,Jackson 会执行一个“将首字母小写”的操作,但由于首字母 c 已经是小写,所以此步骤不做任何改变。

    • 结果: calertFormula

  4. 生成最终的 JSON 键名
    推导过程结束,Jackson 将 calertFormula 确定为与该 getter 方法对应的 JSON 属性名。

总结对比

为了让这个转换更清晰,请看下面的对比:

步骤输入处理逻辑输出
1. 移除前缀getcAlertFormula移除 getcAlertFormula
2. 解耦首字母缩略词cAlertFormula识别 cA,将 A 及后续连续大写字母转小写直到遇到小写字母 (l)calertFormula
3. 首字母小写化calertFormula首字母 c 已小写,无变化calertFormula
最终 JSON 键名calertFormula

核心原因

这个“问题”的根本原因是:

  1. JavaBean 规范要求 Lombok 为字段 cAlertFormula 生成名为 getcAlertFormula() 的方法(首字母 c 不大写)。

  2. Jackson 的默认属性推导器有一个内置规则,专门用于处理这种“畸形”的方法名,它假设 cA 是一个首字母缩略词(如 c 代表 “customer”),并试图通过将 A 转为小写来“修复”它,从而错误地生成了 calertFormula

总结与解决方案

步骤参与者输入输出规则
1Lombok字段 cAlertFormula方法 getcAlertFormula()JavaBean 规范(特殊情况)
2Jackson方法 getcAlertFormula()JSON 字段 calertFormula无脑移除 “get” 并小写首字母

如何解决这个问题?

你有几种选择:

  1. 使用 Jackson 注解(最常用、最清晰):在你的字段上使用 @JsonProperty 来显式指定序列化后的名称,覆盖默认推导行为。

    @Getter @Setter
    public class MyClass {@JsonProperty("cAlertFormula") // 显式指定JSON字段名private String cAlertFormula;
    }
  2. 使用修改 RestTemplateConfig 方案:配置通过 setVisibility 让 Jackson 直接访问字段而不是通过 getter 方法。这意味着:

    • Lombok 仍然会生成 getcAlertFormula() 方法。

    • 但 Jackson 会完全忽略它,直接去读取字段 cAlertFormula 本身。

    • 因此,JSON 键名将直接使用字段名 cAlertFormula
      这就是你提供的配置类能解决这个问题的根本原因。 它绕过了整个由 getter 方法名推导 JSON 键名的过程。

      @Configuration
      public class RestTemplateConfig {@Beanpublic RestTemplate restTemplate() {RestTemplate restTemplate = new RestTemplate();// 配置ObjectMapper以确保JSON序列化行为一致ObjectMapper objectMapper = new ObjectMapper();// 设置驼峰命名策略objectMapper.setPropertyNamingStrategy(PropertyNamingStrategies.LOWER_CAMEL_CASE);// 设置可见性,忽略getter/setter方法,只使用字段objectMapper.setVisibility(objectMapper.getSerializationConfig().getDefaultVisibilityChecker().withGetterVisibility(JsonAutoDetect.Visibility.NONE).withSetterVisibility(JsonAutoDetect.Visibility.NONE).withFieldVisibility(JsonAutoDetect.Visibility.ANY));// 创建并配置Jackson消息转换器MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();converter.setObjectMapper(objectMapper);// 将配置好的转换器添加到RestTemplateList<org.springframework.http.converter.HttpMessageConverter<?>> converters = new ArrayList<>();converters.add(converter);restTemplate.setMessageConverters(converters);return restTemplate;}
      }
      

http://www.dtcms.com/a/341780.html

相关文章:

  • GIT总结一键式命令清单(顺序执行)
  • redis---常用数据类型及内部编码
  • 官网SSO登录系统的企业架构设计全过程
  • 七十四、【Linux数据库】MySQL数据库存储引擎
  • 11让LLM更懂FunctionCalling返回值
  • S32K3 的图形化配置和EB配置mcal差异
  • week2-[二维数组]排队
  • MySQL/Kafka数据集成同步,增量同步及全量同步
  • Windows 如何清理右键菜单?电脑桌面右键菜单里出现一个清理内存 怎么去掉?
  • 数据结构中邻接矩阵中的无向图和有向图
  • 流固耦合|01流固耦合分类
  • 面试 TOP101 二分查找/排序专题题解汇总Java版(BM17 —— BM22)
  • Alpha测试:软件上线前的关键环节
  • 意象框架:连接感知与认知的统一信息结构分析——基于上古汉语同源词意义系统的词源学与认知语言学探索
  • 深入理解与应用向量嵌入(Vector Embeddings):原理、实现与多场景实践
  • 轻量级流程编排框架,Solon Flow v3.5.0 发布
  • WEB安全篇:浏览器攻击原理及防护
  • 软件设计师——数据结构与算法基础学习笔记
  • mac安装Trae并解决App Unavailable问题
  • 【Java进阶】Java JIT 编译器深度解析与优化实践
  • 49.Seata-XA模式
  • Day57 Java面向对象12 多态
  • 齐次线性方程组最小二乘解
  • 压缩包密码找回工具递归解压增强版使用说明
  • 机器学习数据预处理学习报告
  • Linux用30秒部署Nginx+Tomcat+Mysql+Jdk1.8环境
  • Paging in Operating System
  • windows server 彻底卸载oracle 11g
  • Linux命令大全-ps命令
  • AdaCoT:基于强化学习的帕累托最优自适应思维链触发机制