如何递归遍历嵌套JSON,仅替换键名内连字符为下划线以适配BigQuery导入
JSON键名合规化处理(适配BigQuery导入要求)
核心实现思路
针对“不能全局替换字符串、怕误伤属性值内连字符”的约束,我们仅对对象自身的可枚举键名做连字符替换,全程不触碰属性值内容,通过递归逻辑适配任意深度的嵌套结构,完全不需要提前预知JSON的具体层级:
- 遇到普通对象:新建空对象,遍历所有自有键,将键名中的
-替换为_,再对键对应的属性值递归执行同样的处理 - 遇到数组:遍历数组内的每一个元素,对元素递归执行处理,不修改数组本身的长度和顺序
- 遇到原始值(字符串、数字、布尔、null、undefined):直接原样返回,不做任何加工
可直接复用的JavaScript递归实现
function sanitizeJsonKeysForBQ(input) { // 空值直接返回 if (input == null) return input; // 数组类型:逐元素递归处理 if (Array.isArray(input)) { return input.map(item => sanitizeJsonKeysForBQ(item)); } // 仅处理纯对象,跳过Date、自定义类实例等特殊类型 if (typeof input === 'object' && input.constructor === Object) { return Object.keys(input).reduce((target, originalKey) => { // 仅对键名做连字符替换,完全不处理键对应的值内容 const safeKey = originalKey.replace(/-/g, '_'); // 递归处理嵌套值 target[safeKey] = sanitizeJsonKeysForBQ(input[originalKey]); return target; }, {}); } // 原始值直接返回 return input; }
实操避坑点
- 处理过程中必须新建对象/数组存储处理结果,不要直接在原JSON对象上修改键名,否则遍历过程中键名变动很容易出现漏遍历、重复处理的问题
- 处理完成后一定要做重名校验:如果原JSON中同时存在
field-name和field_name两个键,替换后会生成同名键field_name,直接导入BigQuery会触发schema冲突,这类场景需要提前加冲突处理逻辑(比如给重名键加序号后缀) - 这套逻辑完全动态适配结构,不管是多层对象嵌套、对象套数组、数组套对象的复杂结构,都能自动遍历到所有层级的键,不需要针对PageSpeed API的返回结构写硬编码适配规则
内容的提问来源于stack exchange,提问作者Code Guy
相关产品推荐
相关产品推荐

