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

使用Builder模式时如何实现Jackson驼峰键自动转蛇形键

问题根因

@JsonProperty注解会同时控制序列化、反序列化的字段名,优先级高于全局配置的PropertyNamingStrategy,你为了匹配上游返回的驼峰键加了@JsonProperty("myBanner"),导致序列化输出时也强制使用了驼峰命名,覆盖了全局蛇形配置。

以下三种方案均支持保留Builder用法,可按需选择:


方案1:最小改动,用@JsonAlias替代@JsonProperty

@JsonAlias仅在反序列化阶段作为备用键名匹配,不会影响序列化规则,序列化仍会遵循全局蛇形命名策略输出下划线格式的键。
修改后的实体类示例:

@Getter
@Builder
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonDeserialize(builder = Layout.LayoutBuilder.class)
public class Layout {
    // 仅反序列化时识别myBanner,序列化自动输出my_banner
    @JsonAlias("myBanner")
    private final String myBanner;
}

方案2:架构优化,拆分序列化/反序列化ObjectMapper

你当前存在两个互斥的JSON格式诉求:反序列化上游接口的驼峰JSON、序列化返回给客户端的蛇形JSON,共用同一个ObjectMapper会导致规则冲突。
可以给调用上游接口的RestTemplate/WebClient单独配置专用的ObjectMapper,全局MVC的ObjectMapper保留原有蛇形配置即可,实体类无需加任何字段级注解:

// 专门用来调用上游接口的RestTemplate配置
@Bean
public RestTemplate upstreamRestTemplate() {
    RestTemplate restTemplate = new RestTemplate();
    MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
    // 该ObjectMapper仅做上游驼峰JSON的反序列化,不需要配置蛇形命名
    converter.setObjectMapper(new ObjectMapper()
        .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false));
    // 提高该转换器的优先级
    restTemplate.getMessageConverters().add(0, converter);
    return restTemplate;
}

调用上游接口时使用这个自定义的upstreamRestTemplate即可。


方案3:兜底方案,手动递归转换JSON键

如果不想调整现有注解和配置,可在返回响应前将对象转为JSON节点,递归替换所有驼峰键为蛇形键再输出,工具类示例:

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.base.CaseFormat;

public class CamelToSnakeConverter {
    private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();

    public static JsonNode convert(JsonNode node) {
        if (node.isObject()) {
            ObjectNode resNode = OBJECT_MAPPER.createObjectNode();
            node.fields().forEachRemaining(entry -> {
                String snakeKey = CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, entry.getKey());
                resNode.set(snakeKey, convert(entry.getValue()));
            });
            return resNode;
        } else if (node.isArray()) {
            var arrayNode = OBJECT_MAPPER.createArrayNode();
            node.elements().forEachRemaining(element -> arrayNode.add(convert(element)));
            return arrayNode;
        }
        return node;
    }
}

内容的提问来源于stack exchange,提问作者Fllappy

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 23:30:02