You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot 3升级后GSON序列化API响应字段异常问题

Spring Boot 3.1.4 API响应字段名异常排查及实现评估

背景

  • Spring Boot版本从2.6.7升级至3.1.4,已更新所有依赖并重新导入包
  • 多租户架构,基于PostgreSQL数据库
  • 通过原生SQL查询获取JSON格式结果,再转换为指定Java对象返回API响应

核心实现

原生SQL查询

select Row_to_json(list) as response, row_number() over() as id from (
select * from sch.employees )list

EntityManager结果转换方法

public <T> Optional<List<T>> getResultList(String[] parametersName, Object[] parametersValues, Class<T> klazz,
          String queryString) {
      try {
          Query nativeQuery = em.createNativeQuery(queryString, NativeQueryResponse.class);
          for (int i = 0; i < parametersName.length; i++) {
              nativeQuery.setParameter(parametersName[i], parametersValues[i]);
          }
          List<NativeQueryResponse<T>> details = nativeQuery.getResultList();
          Type typeOfT = TypeToken.getParameterized(List.class, klazz).getType();

          List<T> response;
          if (!details.isEmpty() && details.get(0).getResponse() instanceof List) {
              response = (List<T>) details.get(0).getResponse();
          } else {
              response = details.stream().map(NativeQueryResponse::getResponse)
                      .collect(Collectors.toCollection(ArrayList::new));
          }

          em.clear();
          return Optional.of(gson.fromJson(gson.toJson(response), typeOfT));
      } catch (Exception e) {
          log.error("error while executing query {} with parameters as {} and parameters values as {} ", queryString,
                  parametersName, parametersValues);
          CommonUtils.printStackTrack(e);
          return Optional.empty();
      }
  }

映射类定义

NativeQueryResponse

public class NativeQueryResponse<T> {
    @Id
    @Column(name = "id", updatable = false, nullable = false)
    private Long id;

    @Type(JsonType.class)
    @Column(columnDefinition = "jsonb")
    T response;

}

Employee目标类

@Setter
@Getter
public class Employee {
    
    @SerializedName(value = "id")
    private Long id;

    @SerializedName(value = "first_name")
    private String firstName;

    @SerializedName(value = "middle_name")
    private String middleName;

    @SerializedName(value = "dob")
    private String dob;
}

问题现象

  • Controller层中Employee对象的属性已正确赋值(如firstName等Java驼峰属性有对应值)
  • API响应返回的字段名却是@SerializedName定义的数据库风格名称(如first_name),而非预期的Java驼峰命名(如firstName)
  • 所有使用GSON反序列化的API均存在此问题,但通过JPA Repository获取数据的API响应正常
  • 已配置spring.http.converters.preferred-json-mapper: gson,问题未得到解决

相关配置

Spring Security配置

@Bean
  SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
      http.csrf(AbstractHttpConfigurer::disable).authorizeHttpRequests(
              request -> request.requestMatchers(HttpMethod.OPTIONS).permitAll().requestMatchers("/**").permitAll())
              .sessionManagement(manager -> manager.sessionCreationPolicy(STATELESS))
              .addFilterBefore(new AuthenticationFilter(environment), UsernamePasswordAuthenticationFilter.class);
      return http.build();
  }

Maven配置片段

<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<project.reports.dir>${basedir}/target/reports</project.reports.dir>
<java.version>20</java.version>
<maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
<json-path.version>2.4.0</json-path.version>
<org.projectlombok.version>1.18.24</org.projectlombok.version>
<org.mapstruct.version>1.5.5.Final</org.mapstruct.version>
<log4j2.version>2.17.0</log4j2.version>

请求

  1. 排查API响应字段名异常的根本原因
  2. 评估当前原生查询+GSON转换的实现是否符合Spring Boot 3.x的最佳实践

内容的提问来源于stack exchange,提问作者Ranveer Singh Rajpurohit

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 16:33:18