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

3 阅读5分钟

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

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

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

阅读时间:约 5 分钟


一、问题描述

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

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

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

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

前端传参:{ "user_name": "张三", "user_age": 25 }

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


二、问题根源

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

核心机制

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

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

# 全局搜索
grep -r "property-naming-strategy" .
grep -r "spring.jackson" .

常见问题配置:

# ❌ 问题配置
spring:
  jackson:
    property-naming-strategy: SNAKE_CASE
    # 或
    property-naming-strategy: CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES

2️⃣ 检查自定义配置类

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

grep -r "ObjectMapper" .
grep -r "PropertyNamingStrategies" .

常见问题代码:

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

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

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


四、解决方案

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

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

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

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

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

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

优点

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

缺点

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

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

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

spring:
  jackson:
    mapper:
      ACCEPT_CASE_INSENSITIVE_PROPERTIES: true

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


五、方案对比

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

六、最佳实践配置

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

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️⃣ 前端恢复小驼峰传参

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

3️⃣ 后端添加日志验证

@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️⃣ 检查日志输出

✅ 正常输出:
接收到的参数: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 的配置单独处理

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

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

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