前言在日常开发中你是否遇到过这样的情况前端明明传递了参数后端实体类也有对应的字段但数据就是接收不到特别是在使用像cCoatSurStatusDesc这样不太规范的字段名时问题尤为突出。本文将从源码层面深入剖析JsonProperty注解的工作原理帮你彻底理解这个问题。一、问题场景重现假设我们有这样一个场景前端传递的 JSON 数据json{ cCoatSurStatusDesc: 100 }后端实体类javapublic class ASXQ0004 { private String cCoatSurStatusDesc; // getter/setter... }Controller 接收javaPostMapping(/save) public Response save(RequestBody ASXQ0004 entity) { System.out.println(entity.getCCoatSurStatusDesc()); // 输出null ❌ return Response.success(); }奇怪的是明明字段名一模一样为什么就是接收不到呢二、问题根源Java Bean 命名规范2.1 Java Bean 规范根据 Java Bean 规范属性名的定义遵循以下规则属性名以小写字母开头多个单词组成时使用驼峰命名前两个字母要么全是小写要么全是大写java// ✅ 规范的命名 private String userName; // 前两个字母us全小写 private String idNumber; // 前两个字母id全小写 private String URL; // 前两个字母UR全大写 // ❌ 不规范的命名 private String cCoatSurStatusDesc; // 前两个字母cC小写大写混合2.2 Lombok 生成的方法名当我们使用 Lombok 的Data注解时它会根据字段名自动生成 Getter/Setter 方法。对于规范字段javaprivate String userName; // Lombok 生成 public String getUserName() { return userName; } public void setUserName(String userName) { this.userName userName; }对于不规范字段cCoatSurStatusDescjavaprivate String cCoatSurStatusDesc; // Lombok 生成 public String getCCoatSurStatusDesc() { return cCoatSurStatusDesc; } // ↑ 注意C 变成了大写 public void setCCoatSurStatusDesc(String cCoatSurStatusDesc) { this.cCoatSurStatusDesc cCoatSurStatusDesc; } // ↑ 注意C 是大写的三、Jackson 的反序列化机制3.1 Jackson 的默认行为Jackson 在反序列化JSON → Java 对象时优先使用 Setter 方法而不是直接操作字段。Jackson 如何找到 Setter 方法Jackson 根据 JSON 中的字段名cCoatSurStatusDesc推断 Setter 方法名textJSON 字段名: cCoatSurStatusDesc ↓ 推断 Setter 名: setCcoatSurStatusDesc() ← 注意c 是小写 ↓ 反射查找方法: Class.getMethod(setCcoatSurStatusDesc, String.class) ↓ ❌ 找不到因为 Lombok 生成的是 setCCoatSurStatusDesc() ↓ 通过字段反射赋值 → 但 Jackson 默认优先使用 Setter ↓ 最终结果null3.2 方法名对比来源方法名结果Lombok 生成setCCoatSurStatusDesc()✅ 存在Jackson 推断setCcoatSurStatusDesc()❌ 不存在是否匹配❌不匹配这就是问题的本质Lombok 和 Jackson 对同一个字段生成了不同的方法名四、JsonProperty 如何解决问题4.1 添加注解后javapublic class ASXQ0004 { JsonProperty(cCoatSurStatusDesc) private String cCoatSurStatusDesc; }4.2 Jackson 的行为变化加了JsonProperty后Jackson 不再依赖 Setter 方法名推断而是直接通过反射访问字段绕过了 Setter 方法显式指定了 JSON 字段名不会产生歧义textJSON 字段名: cCoatSurStatusDesc ↓ JsonProperty 指定: cCoatSurStatusDesc ↓ Jackson 直接通过字段反射赋值 ↓ Field.set(cCoatSurStatusDesc, 300) ✅ 成功4.3 源码分析Jackson 在反序列化时的核心逻辑java// 简化版 Jackson 核心逻辑 public Object deserialize(JsonParser p, DeserializationContext ctxt) { // 1. 查找 JsonProperty 注解 JsonProperty ann _findAnnotation(JsonProperty.class); if (ann ! null) { // 2. 有注解使用注解指定的名称 String propName ann.value(); // cCoatSurStatusDesc // 3. 直接通过字段反射赋值跳过 Setter _field.set(obj, value); } else { // 4. 无注解通过 Java Bean 规范推断方法名 String setterName set capitalize(propName); // 对于 cCoatSurStatusDesc → setCcoatSurStatusDesc() Method setter cls.getMethod(setterName, type); setter.invoke(obj, value); } }五、其他解决方案对比5.1 方案一使用 JsonProperty推荐javaJsonProperty(cCoatSurStatusDesc) private String cCoatSurStatusDesc;优点简单直接只需加一个注解缺点每个不规范的字段都需要加5.2 方案二改为标准命名java// 改为规范的驼峰命名 private String coatSurStatusDesc; // 前两个字母co全小写✅优点一劳永逸不需要任何额外注解缺点需要修改字段名可能影响已有代码5.3 方案三使用 SerializedNameGsonjavaSerializedName(cCoatSurStatusDesc) private String cCoatSurStatusDesc;5.4 方案四使用 JacksonizedLombok 扩展javaJacksonized Data public class ASXQ0004 { private String cCoatSurStatusDesc; }六、总结6.1 问题本质问题原因为什么接收不到数据Lombok 生成setCCoatSurStatusDesc()Jackson 找setCcoatSurStatusDesc()两者不一致为什么加了 JsonProperty 就好注解告诉 Jackson 直接通过字段反射赋值绕过了 Setter 方法6.2 核心要点Java Bean 规范属性名前两个字母不能大小写混合Lombok 问题对不规范字段生成的方法名不符合预期Jackson 机制默认优先使用 Setter 方法JsonProperty 作用绕过 Setter直接通过字段反射赋值6.3 一句话总结cCoatSurStatusDesc违反了 Java Bean 命名规范导致 Lombok 生成的 Setter 方法名setCCoatSurStatusDesc与 Jackson 推断的方法名setCcoatSurStatusDesc不匹配加上JsonProperty后Jackson 直接通过字段反射赋值绕过了 Setter 方法从而成功接收到数据。附录快速参考场景解决方案字段名不规范加JsonProperty注解想彻底解决改为标准驼峰命名数据库映射加TableField注解JSON 序列化JsonProperty同时控制序列化和反序列化希望这篇文章能帮你彻底理解 JsonProperty 的工作原理如有疑问欢迎在评论区交流讨论。