如何在JavaScript与NestJS中将TypeORM返回的JSON对象转换为原始数据
实现方案
核心逻辑
你需要做的就是两步:1. 把嵌套对象按路径拍平为单层键值对;2. 把顶层的关联数组字段拆分为多条结果,每条都携带顶层公共字段,最终输出的结果格式和TypeORM内置的getRawMany()返回格式完全一致。
代码实现
1. 通用对象拍平函数
/** * 把嵌套对象拍平为单层对象,键为路径拼接 * @param {object} obj 待拍平的对象 * @param {string} parentKey 父级键前缀 * @param {string} separator 路径分隔符,默认和TypeORM raw返回一致用下划线 * @returns {object} 拍平后的单层对象 */ function flattenObject(obj, parentKey = '', separator = '_') { return Object.entries(obj).reduce((result, [key, value]) => { const currentKey = parentKey ? `${parentKey}${separator}${key}` : key; // 非数组的嵌套对象递归处理 if (typeof value === 'object' && value !== null && !Array.isArray(value)) { Object.assign(result, flattenObject(value, currentKey, separator)); } else { result[currentKey] = value; } return result; }, {}); }
2. 实体转Raw数组函数
/** * 将TypeORM返回的嵌套实体对象转换为和getRawMany()格式一致的原始数组 * @param {object} typedResult TypeORM查询得到的实体对象 * @param {string} arrayFieldName 顶层一对多关联的数组字段名,你示例中为`xxxx` * @returns {object[]} 拍平后的原始数据数组 */ function convertToRaw(typedResult, arrayFieldName) { // 拆分公共字段和数组字段 const { [arrayFieldName]: arrayData, ...commonFields } = typedResult; // 数组为空时直接返回公共字段拍平后的单条结果 if (!arrayData?.length) { return [flattenObject(commonFields)]; } // 遍历数组项,合并公共字段后拍平 return arrayData.map(item => { const mergedItem = { ...commonFields, [arrayFieldName]: item }; return flattenObject(mergedItem); }); }
使用示例
// 你从TypeORM获取到的嵌套结果 const typeormResult = { "sysUserID":"", "personID":1383, "xxxx":[ { "sysRoleID":"", "institution":{ "town":{ "townID":null, "name":"", "municipality":{} } } }, { "sysRoleID":0, "institution":{ "town":{ "name":"", "municipality":{} } } } ], "person":{} } // 调用转换方法 const rawData = convertToRaw(typeormResult, 'xxxx'); console.log(rawData);
自定义调整
- 如果需要修改键的分隔符,比如用驼峰格式,调整
flattenObject的separator参数以及拼接逻辑即可 - 如果需要展开数组类型的字段值,可以在
flattenObject中补充数组类型的判断逻辑 - 存在多个顶层数组字段的场景,可自行扩展逻辑对多个数组做笛卡尔积拼接
内容的提问来源于stack exchange,提问作者Ivelin
相关产品推荐
相关产品推荐

