【SpringBoot】 前后端参数命名踩坑记录:小驼峰变下划线导致接收不到参数

Spring Boot 前后端参数命名踩坑记录:小驼峰变下划线导致接收不到参数

问题现象:前端传小驼峰,后端 DTO 也是小驼峰,但接收不到参数;改成下划线反而能收到。

适用版本:Spring Boot 2.x / 3.x

阅读时间:约 5 分钟


一、问题描述

最近在项目开发中遇到一个诡异的问题:

vbnet 复制代码
前端传参:{ "userName": "张三", "userAge": 25 }
后端 DTO:
public class UserDTO {
    private String userName;
    private Integer userAge;
}

结果 :后端接收到的字段全是 null

但奇怪的是,当前端把参数改成下划线命名后:

json 复制代码
前端传参:{ "user_name": "张三", "user_age": 25 }

结果:后端正常接收到了数据!


二、问题根源

经过排查,发现问题出在 Jackson 的命名策略配置 上。

核心机制

Spring Boot 默认使用 Jackson 进行 JSON 的序列化和反序列化。当配置了以下参数时:

yaml 复制代码
spring:
  jackson:
    property-naming-strategy: SNAKE_CASE

Jackson 会在反序列化时自动将前端传来的驼峰参数转换为下划线,导致匹配失败:

复制代码
┌─────────────────────────────────────────────────────────────┐
│                    请求处理流程                              │
├─────────────────────────────────────────────────────────────┤
│  前端传参          Jackson 反序列化          后端 DTO        │
│  ──────          ────────────────          ────────        │
│  userName   →   转为 user_name    →   userName  ❌ 不匹配    │
│  userAge    →   转为 user_age     →   userAge   ❌ 不匹配    │
└─────────────────────────────────────────────────────────────┘

关键点

⚠️ property-naming-strategy 同时影响序列化和反序列化!

很多人以为它只影响后端返回给前端的格式,其实它也会影响前端传给后端的参数解析。


三、排查步骤

1️⃣ 检查配置文件

搜索项目中的 application.ymlapplication.properties

bash 复制代码
# 全局搜索
grep -r "property-naming-strategy" .
grep -r "spring.jackson" .

常见问题配置:

yaml 复制代码
# ❌ 问题配置
spring:
  jackson:
    property-naming-strategy: SNAKE_CASE
    # 或
    property-naming-strategy: CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES

2️⃣ 检查自定义配置类

搜索项目中是否有自定义的 ObjectMapper

bash 复制代码
grep -r "ObjectMapper" .
grep -r "PropertyNamingStrategies" .

常见问题代码:

java 复制代码
// ❌ 问题代码
@Configuration
public class JacksonConfig {
    @Bean
    public ObjectMapper objectMapper() {
        ObjectMapper mapper = new ObjectMapper();
        mapper.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE);
        return mapper;
    }
}

3️⃣ 检查父工程或 Starter 依赖

有些公司内部的 starter 或父工程可能默认配置了命名策略,需要检查依赖传递的配置。


四、解决方案

方案一:移除命名策略配置(推荐)

适用场景:前后端统一使用小驼峰命名

yaml 复制代码
# application.yml
spring:
  jackson:
    # ✅ 删除或注释掉这行
    # property-naming-strategy: SNAKE_CASE
    
    # ✅ 或者显式设置为 null(使用默认驼峰)
    property-naming-strategy: null
java 复制代码
// 自定义配置类修改
@Configuration
public class JacksonConfig {
    @Bean
    public ObjectMapper objectMapper() {
        ObjectMapper mapper = new ObjectMapper();
        // ✅ 移除或设置为 null
        mapper.setPropertyNamingStrategy(null);
        return mapper;
    }
}

方案二:使用 @JsonAlias 兼容多种命名

适用场景:需要同时支持驼峰和下划线,增加容错性

java 复制代码
public class UserDTO {
    
    @JsonAlias({"userName", "user_name"})
    private String userName;
    
    @JsonAlias({"userAge", "user_age"})
    private Integer userAge;
    
    // getter 和 setter
}

优点

  • ✅ 同时兼容两种命名方式
  • ✅ 前端改动成本低
  • ✅ 不影响其他接口

缺点

  • ⚠️ 字段多时需要逐个添加注解

方案三:开启大小写不敏感

适用场景:需要增加参数匹配的容错性

yaml 复制代码
spring:
  jackson:
    mapper:
      ACCEPT_CASE_INSENSITIVE_PROPERTIES: true

注意:此配置只忽略大小写,不解决驼峰与下划线的转换问题,建议配合方案一使用。


五、方案对比

方案 配置位置 影响范围 推荐度
移除命名策略 application.yml 全局 ⭐⭐⭐⭐⭐
@JsonAlias DTO 字段 单个字段 ⭐⭐⭐⭐
大小写不敏感 application.yml 全局 ⭐⭐⭐
自定义 ObjectMapper 配置类 全局 ⭐⭐⭐

六、最佳实践配置

以下是推荐的全局 Jackson 配置,兼顾规范性和容错性:

yaml 复制代码
spring:
  jackson:
    # 使用默认驼峰命名(前后端统一小驼峰)
    property-naming-strategy: null
    
    # 忽略大小写,增加容错性
    mapper:
      ACCEPT_CASE_INSENSITIVE_PROPERTIES: true
    
    # 日期格式
    date-format: yyyy-MM-dd HH:mm:ss
    time-zone: Asia/Shanghai
    
    # 空值处理:序列化时忽略 null 字段
    default-property-inclusion: non_null
    
    # 反序列化时允许未知字段(防止前端多传参数报错)
    deserialization:
      fail-on-unknown-properties: false

七、验证方法

修改配置后,按以下步骤验证:

1️⃣ 重启服务

确保配置生效。

2️⃣ 前端恢复小驼峰传参

javascript 复制代码
// API 请求
axios.post('/api/user', {
  userName: '张三',
  userAge: 25
})

3️⃣ 后端添加日志验证

java 复制代码
@PostMapping("/user")
public Result createUser(@RequestBody UserDTO dto) {
    log.info("接收到的参数:{}", dto);
    log.info("userName: {}", dto.getUserName());
    log.info("userAge: {}", dto.getUserAge());
    return Result.success();
}

4️⃣ 检查日志输出

ini 复制代码
✅ 正常输出:
接收到的参数:UserDTO(userName=张三, userAge=25)
userName: 张三
userAge: 25

❌ 异常输出:
接收到的参数:UserDTO(userName=null, userAge=null)

八、总结

问题 原因 解决
小驼峰接收不到 Jackson 配置了下划线命名策略 移除或修改 property-naming-strategy
下划线能收到 命名策略将驼峰转为下划线后匹配成功 证明配置确实生效了
部分接口正常 可能某些 Controller 用了 @JsonAlias 统一配置规范

核心要点

  1. property-naming-strategy 同时影响序列化和反序列化
  2. 前后端命名规范应统一(推荐都用小驼峰)
  3. 配置修改后务必重启服务
  4. 善用 @JsonAlias 增加容错性

九、延伸思考

为什么有人要配置下划线命名?

  1. 数据库字段规范:数据库常用下划线,方便实体类映射
  2. 团队规范:有些团队要求 API 统一使用下划线
  3. 历史遗留:老项目迁移时的兼容需求

如果确实需要输出下划线怎么办?

可以分离序列化和反序列化策略 ,但这需要自定义 ObjectMapper,复杂度较高。更推荐的做法是:

前后端统一使用小驼峰,后端与数据库的映射通过 MyBatis/JPA 的配置单独处理

yaml 复制代码
# MyBatis 配置(只影响数据库映射,不影响 API)
mybatis:
  map-underscore-to-camel-case: true

📌 收藏本文,遇到类似问题快速排查!

💬 你有遇到过类似的前后端参数命名问题吗?欢迎在评论区分享你的解决方案!

相关推荐
武子康4 小时前
Java-07 深入浅出 MyBatis数据库一对多关系模型实战:表结构设计与查询实现
java·后端
花椒技术5 小时前
企业内部 Agent 落地复盘:Gateway、Skill 和二次确认如何串起受控业务执行
后端·agent·ai编程
我是一颗柠檬7 小时前
【MySQL全面教学】MySQL事务与ACID Day9(2026年)
数据库·后端·mysql
枕星而眠7 小时前
数据结构八大排序详解(一):四大简单排序
c语言·数据结构·c++·后端
IT_陈寒7 小时前
React useEffect闭包陷阱差点把我整失业了
前端·人工智能·后端
苍何8 小时前
爆肝两周,我把 Codex 最全实战指南开源了
后端
bug菌8 小时前
【SpringBoot 3.x 第254节】夯爆了,数据库访问性能优化实战详解!
数据库·spring boot·后端
Rust研习社8 小时前
从碎片化到标准化:cargo-bp 如何重构 Rust 开发逻辑
后端·rust·编程语言
锋行天下9 小时前
一句mysql复杂查询搞崩一个壮汉
后端·mysql·go
不肯过江东丶9 小时前
大聪明教你学Java | Spring AI Lab:一个让你 3 分钟接入 AI 对话能力的 Spring Boot 工具箱
spring boot·后端