
本文介绍如何基于 json 路径(如 `$.offer.custom_fields.job_title`)自动提取嵌套对象的所有可映射字段,并与预定义的字段映射配置进行匹配,生成包含 `externalfieldid` 和对应 `integrationfieldid` 的标准化映射列表,缺失映射则置为空字符串。
在构建集成系统(如 HRIS ↔ ATS 数据同步)时,常需将源对象(如 API 响应)的嵌套字段路径与目标系统字段(如 $.engagementData.title)建立双向映射关系。本教程提供一种轻量、可复用的 TypeScript 方案,用于自动发现源对象所有深层字段路径,并精确匹配预设的映射规则,最终生成符合预期结构的映射清单。
✅ 核心步骤说明
- 递归提取所有字段路径:使用深度优先遍历,将嵌套对象转为标准 JSONPath 格式(如 $.offer.custom_fields.job_title);
- 匹配映射配置:遍历每个提取出的 externalFieldId,查找 defaultFieldMapping 中 path 值完全相等的条目,获取其 key(即 integrationFieldId);
- 补全未映射字段:对源对象中存在但未在 defaultFieldMapping 中声明的字段(如 $.offer.job_post),保留其路径并设置 integrationFieldId: ''。
? 实现代码(TypeScript 兼容)
function getDeepKeys(obj: Record): string[] { function* _getDeepKeys( current: Record , prefix: string ): Generator { for (const [key, value] of Object.entries(current)) { const path = `${prefix}${key}`; if (value !== null && typeof value === 'object' && !Array.isArray(value)) { yield* _getDeepKeys(value, `${path}.`); } else { yield path; } } } return [..._getDeepKeys(obj, '$.')]; } // 示例数据 const response = { offer: { custom_fields: { job_title: 'engineer', }, starts_at: 'test', job_post: 'test', }, }; const defaultFieldMapping = { '$.engagementData.title': { default: 'Software Engineer', path: '$.offer.custom_fields.job_title', fieldName: 'Title', }, '$.engagementData.startDateUTC': { default: null, path: '$.offer.starts_at', }, }; // 生成映射结果 const result = getDeepKeys(response).map(externalFieldId => { const matchedEntry = Object.entries(defaultFieldMapping).find( ([_, config]) => config.path === externalFieldId ); return { externalFieldId, integrationFieldId: matchedEntry ? matchedEntry[0] : '', }; }); console.log(result); // 输出: // [ // { externalFieldId: "$.offer.custom_fields.job_title", integrationFieldId: "$.engagementData.title" }, // { externalFieldId: "$.offer.starts_at", integrationFieldId: "$.engagementData.startDateUTC" }, // { externalFieldId: "$.offer.job_post", integrationFieldId: "" } // ]
⚠️ 注意事项
- 路径格式一致性:确保 response 对象的字段路径与 defaultFieldMapping.path 完全一致(包括 $. 前缀和点号分隔),否则匹配失败;
- 避免数组干扰:当前 getDeepKeys 默认跳过数组(因 JSONPath 中数组索引需显式处理,如 $.items[0].name),如需支持数组,请扩展逻辑以识别 Array.isArray(value) 并递归处理各元素;
- 性能考量:对于超深或超大嵌套对象,建议增加递归深度限制或改用栈式迭代实现;
-
TypeScript 类型增强(推荐):
interface FieldMappingConfig { default: any; path: string; fieldName?: string; } type FieldMapping = Record;
该方案简洁可靠,无需外部依赖,可直接集成至数据适配层、ETL 配置工具或低代码映射编辑器中,显著提升字段映射的自动化程度与可维护性。










