Java递归转换JSON所有驼峰键为小写下划线命名格式
驼峰命名JSON递归转蛇形命名实现方案
核心实现逻辑不依赖特定语言,所有技术栈的实现都遵循统一流程:
- 先实现单键名转换逻辑:匹配驼峰字符串中不在开头位置的大写字母,在大写字母前插入下划线,再将整个字符串转为小写
- 递归遍历全量JSON结构,按值的类型分别处理:
- 基础类型(字符串、数字、布尔值、null):直接返回原值,不做处理
- 数组/列表:遍历所有元素,对每个元素递归执行转换逻辑,返回新数组
- 对象/字典/哈希结构:遍历所有键,将键转为蛇形格式,对对应的值递归执行转换逻辑,组装成新对象
JavaScript/TypeScript 实现(前端/Node.js场景适用)
/** * 驼峰字符串转蛇形字符串 * @param {string} str 原始驼峰字符串 * @returns {string} 转换后蛇形字符串 */ function camelToSnake(str) { return str.replace(/(?<!^)([A-Z])/g, '_$1').toLowerCase(); } /** * 递归转换JSON全层级键为蛇形格式 * @param {any} data 待转换的驼峰格式JSON * @returns {any} 转换后蛇形格式JSON */ function convertCamelToSnake(data) { // 处理基础类型与null if (data === null || typeof data !== 'object') { return data; } // 处理数组 if (Array.isArray(data)) { return data.map(item => convertCamelToSnake(item)); } // 处理对象 const converted = {}; for (const [key, value] of Object.entries(data)) { converted[camelToSnake(key)] = convertCamelToSnake(value); } return converted; } // 调用示例:传入获取到的驼峰JSON,得到的结果可直接传给第三方API const snakeCaseResult = convertCamelToSnake(camelCaseInput);
如果需要兼容不支持负向零宽断言的极老运行环境,可以把camelToSnake函数替换为遍历字符的实现,避免正则兼容问题。
Java 实现(后端DTO转换场景适用)
方案1:Jackson序列化配置(推荐,无侵入)
Java生态下优先用Jackson的内置命名策略,不需要手写递归,也不需要修改现有业务DTO的属性,自动支持多层嵌套、数组内对象的键转换,完全覆盖需求场景:
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.PropertyNamingStrategies; // 初始化序列化工具,配置全局蛇形命名策略 ObjectMapper snakeCaseMapper = new ObjectMapper(); snakeCaseMapper.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE); // 调用示例:直接将业务侧驼峰DTO/JsonNode序列化为符合第三方要求的JSON String requestBody = snakeCaseMapper.writeValueAsString(yourBusinessDto);
方案2:手写递归工具(无Jackson依赖场景使用)
import java.util.*; import java.util.regex.Pattern; public class CamelToSnakeConverter { private static final Pattern CAMEL_PATTERN = Pattern.compile("(?<!^)([A-Z])"); private static String camelToSnake(String str) { return CAMEL_PATTERN.matcher(str).replaceAll("_$1").toLowerCase(Locale.ROOT); } public static Object convert(Object data) { if (data == null) return null; // 处理基础类型 if (data instanceof String || data instanceof Number || data instanceof Boolean) { return data; } // 处理列表 if (data instanceof List) { List<?> rawList = (List<?>) data; List<Object> convertedList = new ArrayList<>(rawList.size()); for (Object item : rawList) { convertedList.add(convert(item)); } return convertedList; } // 处理Map if (data instanceof Map) { Map<?, ?> rawMap = (Map<?, ?>) data; Map<String, Object> convertedMap = new HashMap<>(rawMap.size()); for (Map.Entry<?, ?> entry : rawMap.entrySet()) { String newKey = camelToSnake(entry.getKey().toString()); convertedMap.put(newKey, convert(entry.getValue())); } return convertedMap; } // 自定义DTO先转Map再处理 throw new IllegalArgumentException("不支持的参数类型,请先将DTO转为Map结构"); } }
Python 实现(数据处理场景适用)
import re from typing import Any def camel_to_snake(s: str) -> str: return re.sub(r'(?<!^)([A-Z])', r'_\1', s).lower() def convert_camel_to_snake(data: Any) -> Any: # 处理基础类型与None if not isinstance(data, (dict, list)): return data # 处理列表 if isinstance(data, list): return [convert_camel_to_snake(item) for item in data] # 处理字典 converted = {} for key, value in data.items(): converted[camel_to_snake(key)] = convert_camel_to_snake(value) return converted # 调用示例 # import json # camel_data = json.loads(raw_camel_json_str) # snake_data = convert_camel_to_snake(camel_data) # 最终将snake_data序列化为JSON即可传给第三方
以上实现均可以正确覆盖给出的样例场景,所有层级的键(包括数组内嵌套对象、多层对象的属性)都会被正确转换,输出格式和期望结果完全一致。
内容的提问来源于stack exchange,提问作者Rajesh Patel
相关产品推荐
相关产品推荐

