You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Google Apps Script导入嵌套JSON数据时列数不匹配异常排查求助

Fix "Columns Mismatch" Error When Importing JSON with Multi-Child Nodes to Google Sheets

咱们先捋清楚你遇到的问题根源:
你的脚本在处理JSON时,表头只固定取了第三个父节点的子节点键,而且直接提取子节点的values却没有和表头的键对应,导致当某些子节点的键数量(比如Child12两个键)和表头的列数不一致时,就会触发列数不匹配的异常。手动加列没用是因为脚本里的范围是根据固定的表头列数计算的,和实际数据的列数对不上。

下面是修复后的完整脚本,我做了这些关键调整:

  1. 自动收集所有子节点的键,生成包含所有字段的完整表头(解决表头不全的问题)
  2. 按表头的键顺序提取每个父节点对应的值,缺失的字段填充空值(保证每行的列数和表头一致)
  3. 修正了range设置的逻辑,确保数据范围和实际数据的行列数匹配
function chunkArray(myArray, chunk_size){
 var index = 0;
 var arrayLength = myArray.length;
 var tempArray = [];
 for (index = 0; index < arrayLength; index += chunk_size) {
 myChunk = myArray.slice(index, index+chunk_size);
 tempArray.push(myChunk);
 }
 return tempArray;
}

function flatten(arrayOfArrays){
 return [].concat.apply([], arrayOfArrays);
}

function insertJSON(){
 var aOneName = "id";
 var sheet = SpreadsheetApp.getActiveSheet();
 var fileURL = "link to .json"
 var res = UrlFetchApp.fetch(fileURL,{'muteHttpExceptions': true});
 var content = res.getContentText();
 var json = JSON.parse(content);
 
 // 获取所有父节点的键
 var parentKeys = Object.keys(json);
 var rows = [parentKeys];
 var toRows = parentKeys.length + 1;
 
 // 把父节点键写入A列
 var rowsflate = flatten(rows);
 var rowstocols = chunkArray(rowsflate, 1);
 sheet.getRange("A2:A" + toRows).setValues(rowstocols);
 sheet.getRange(1, 1).setValue(aOneName);
 
 // 关键修复1:收集所有子节点的键,生成完整的表头(去重并排序)
 let allHeaderKeys = new Set();
 parentKeys.forEach(parentKey => {
   const childNodes = json[parentKey];
   Object.keys(childNodes).forEach(childKey => {
     Object.keys(childNodes[childKey]).forEach(key => allHeaderKeys.add(key));
   });
 });
 const headerKeys = Array.from(allHeaderKeys).sort(); // 排序保证顺序稳定
 const getHeaders = [headerKeys];
 
 // 写入表头到第1行,从D列开始
 sheet.getRange(1,4,getHeaders.length,getHeaders[0].length).setValues(getHeaders);
 
 // 关键修复2:按表头顺序提取每个父节点的对应值,缺失字段填空
 var content = [];
 parentKeys.forEach(parentKey => {
   const parentNode = json[parentKey];
   const rowValues = headerKeys.map(key => {
     // 遍历每个表头键,找到对应的子节点值,没有则返回空字符串
     for (const childKey in parentNode) {
       if (parentNode[childKey].hasOwnProperty(key)) {
         return parentNode[childKey][key];
       }
     }
     return "";
   });
   content.push(rowValues);
 });
 
 // 写入数据:从第2行第1列开始,行数是父节点数量,列数是表头列数
 sheet.getRange(2,1,content.length, headerKeys.length).setValues(content);
}

为什么这样能解决问题?

  • 原来的表头只取了json[rows[0][2]](第三个父节点的子节点),现在改成收集所有出现过的子节点键,不管哪个父节点有多少字段,表头都会包含全部字段。
  • 原来直接用Object.values提取值,现在按表头的键顺序逐个匹配,确保每行的列数和表头完全一致,不会出现有的行多列、有的行少列的情况。
  • 最后写入数据的range是根据实际数据的行列数动态计算的,彻底避免了“数据列数≠范围列数”的异常。

内容的提问来源于stack exchange,提问作者hugo1199

火山引擎 最新活动