如何在 TypeScript 中实现嵌套对象的字段映射关系提取

本文介绍一种通用方法,通过递归遍历响应对象获取所有深层路径,并与预定义的字段映射配置比对,自动生成包含 externalfieldid 与对应 integrationfieldid(或空字符串)的标准化映射列表。

在集成系统开发中,常需将第三方 API 响应中的嵌套字段(如 offer.custom_fields.job_title)映射到内部数据模型字段(如 $.engagementData.title)。为自动化构建这种双向映射关系,关键在于:完整提取源对象所有可访问的 JSON 路径,并精准匹配配置中声明的 path 字段

以下是一个健壮、可复用的 TypeScript 实现:

function getDeepKeys(obj: Record): string[] {
  function* _getDeepKeys(current: any, prefix: string): Generator {
    if (current === null || typeof current !== 'object') {
      return;
    }
    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: "" }
// ]

注意事项与最佳实践

  • 该方案默认忽略数组(Array.isArray(value) 检查),避免生成如 $.items.0.name 这类非确定性路径;如需支持数组索引,可扩展逻辑(例如使用 [*] 占位符)。
  • getDeepKeys 使用生成器函数,内存友好,适用于深层嵌套的大对象。
  • integrationFieldId 为空字符串表示该源字段未被任何映射规则覆盖,便于后续做缺失字段告警或自动填充处理。
  • 在 TypeScript 项目中,建议为 defaultFieldMapping 定义强类型接口(如 FieldMappingConfig),提升类型安全与 IDE 支持。

此方法解耦了数据结构发现与映射逻辑,既可用于初始化配置校验,也可作为 ETL 流程中字段对齐的基础能力。