如何将嵌套数组对象转换为指定键名及驼峰格式?
解决嵌套数组对象的键转换问题:指定键替换+SnakeCase转CamelCase
问题需求
将数组中的对象转换为新对象,需满足:
- 特定旧键替换为指定新键(如
org_id替换为clientDivisionOrganizationId); - 其余SnakeCase格式的键自动转换为CamelCase格式;
- 支持任意层级的嵌套对象和数组转换(如示例中
addresses下的usage_types、address_usages下的嵌套address对象)。
原代码的不足
原转换逻辑仅处理了一层嵌套的对象和数组,无法递归处理更深层级的结构,导致深层嵌套的键(如address_1、usage_types)未按规则转换,且键映射的匹配逻辑不够直观。
改进方案
通过递归函数统一处理所有层级的对象和数组,确保每一层的键都应用转换规则:
- 调整键映射表
newKeyMap,直接用原SnakeCase键作为映射键,便于匹配; - 编写递归转换函数,对每个值的类型做判断:
- 若为非数组、非null的对象:遍历键值对,转换键后递归处理值;
- 若为数组:遍历数组元素,对每个元素递归调用转换函数;
- 若为基本类型:直接保留值。
改进后的代码
const originalArray = [{ "uuid": "65a49008-3291ba-4dc6-8fd8-476c4ea7b84d", "name": "Post-man Hospital-local", "site_number": "PKKk-2219232", "phone": "", "fax": "", "org_id": "PKKKK-2219232", "principal_investigator_user_uuid": null, "study_uuid": "863080a12c-5335-472334-9103-50ea782da3c9", "principal_investigator": { "uuid": null, "email": null, "first_name": null, "last_name": null }, "licenses": [], "has_assigned_users": false, "addresses": [ { "uuid": "60c132a43b-5ab5-434a91-a4ec-d6e4704d4937", "address_1": "Chinchwad", "address_2": "", "address_3": "", "city": "Pune", "state": "MH", "subregion": "MH", "country": "IND", "postal_code": "412105", "translated_country_name": null, "translated_subregion_name": null, "latitude": "18.64742", "longitude": "73.80003", "timezone_name": "Asia/Kolkata", "types": ["main"], "cascaded_at": null, "is_current": true, "usage_types": [{ "name": "main" }] } ], "email_addresses": [], "telecom_addresses": [], "status": "planned", "team_memberships_count": 0, "cascaded_at": null, "address_usages": [ { "uuid": "e58efc53223a-2028-4f7a-bc56-e8d72f4f2c18", "active": true, "usage_types": [{ "name": "main" }], "address": { "uuid": "60c123a43b-5ab5-4a91-a4ec-d6e4704d4937", "address_1": "Chinchwad", "address_2": "", "address_3": "", "city": "Pune", "subregion": "MH", "country": "IND", "postal_code": "412105", "translated_country_name": null, "translated_subregion_name": null, "latitude": "18.64742", "longitude": "73.80003", "timezone_name": "Asia/Kolkata" }, "is_current": true, "cascaded_at": null } ], "active_pi_tm": null, "main_address": { "address_1": "Chinchwad", "address_2": "", "address_3": "", "city": "Pune", "state": "MH", "subregion": "MH", "country": "IND", "postal_code": "412105", "translated_country_name": null, "translated_subregion_name": null, "latitude": "18.64742", "longitude": "73.80003", "timezone_name": "Asia/Kolkata" } }]; // 调整键映射:原SnakeCase键 => 目标键(指定替换或CamelCase) const newKeyMap = { "uuid": "uuid", "site_number": "siteNumber", "name": "siteName", "main_address": "mainAddress", "team_memberships_count": "teamMembershipCount", "has_assigned_users": "hasAssignedUsers", "org_id": "clientDivisionOrganizationId", // 嵌套键如果需要单独替换也可以在这里添加,比如:"address.address_1": "street" }; // SnakeCase转CamelCase工具函数 function camelize(text) { return text.toLowerCase().replace(/[-_\s.]+(.)?/g, (_, c) => c ? c.toUpperCase() : '') .replace(/^[A-Z]/, c => c.toLowerCase()); } // 递归转换单个对象/数组 function transformItem(item) { // 处理数组:遍历每个元素递归转换 if (Array.isArray(item)) { return item.map(transformItem); } // 处理非数组对象:遍历键值对转换 if (typeof item === 'object' && item !== null) { return Object.entries(item).reduce((acc, [key, value]) => { // 确定新键:优先用映射表,否则自动转CamelCase const newKey = newKeyMap[key] || camelize(key); // 递归处理值 acc[newKey] = transformItem(value); return acc; }, {}); } // 基本类型直接返回 return item; } // 转换数组中的所有对象 const transformArrayObject = (originalArray) => { return originalArray.map(transformItem); }; // 测试输出 console.log("Result:", JSON.stringify(transformArrayObject(originalArray), null, 2));
代码说明
- 键映射表优化:
newKeyMap直接使用原数据的SnakeCase键作为键,无需额外转换即可匹配,逻辑更清晰; - 递归函数
transformItem:统一处理数组、对象和基本类型,确保所有嵌套层级都被转换; - CamelCase转换:工具函数
camelize兼容带连字符、下划线的SnakeCase格式,自动转为标准CamelCase; - 灵活性:如果需要对特定嵌套键单独替换,直接在
newKeyMap中添加(如"address.address_1": "street"),但当前逻辑会自动转换嵌套键为CamelCase,无需额外配置。
内容的提问来源于stack exchange,提问作者Pramod Kharade
相关产品推荐
相关产品推荐

