通过 API 将 JSON 拉入 Google Sheet 导致单元格中的值未定义

Pulling JSON into Google Sheet via API resulting in undefined values in cells

我的一个 API 有问题 我正在尝试建立一个 API 来调用名为 Streak 的客户关系管理工具,我正在尝试通过HTTP Basic Auth GET 通过我的脚本逻辑解析 JSON 文件,然后进入我的 Google Sheet 传播 sheet。经过几个小时的开发,Google 应用程序脚本可以完美地工作(满足我的要求)一件事,我的脚本将字符串 'undefined' 插入到我的 google sheet 单元格中每当它找不到一个值时,一个完全空的不存在的字段。

Google Sheet 输出问题的图像如下所示 注意:我已经突出显示了让我感到悲伤的字段属性名称和未定义的值 https://drive.google.com/file/d/0B4rXaBEqs2UzSU5fMFUxYW8zTm8/view?usp=sharing

运行以将数百条记录外推到我的 Google Sheet 的整个代码片段可以在下面看到。据我了解,我的问题出在语句 row.push(字段 1001 -> 1021)中,它总是试图将所有字段推送到 sheet;但是,并非所有记录都包含这些字段,因为我可能没有在源 CRM 中填充它们。作为回应,脚本在我的 Sheet.

中的相应单元格中填充 "undefined" 字符串

我希望防止这个 "undefined" 字符串被填充到 sheet 中,而不是这个单元格应该是空白的,有人可以告诉我如何调整我的代码片段来实现这个?非常感激!我已经尝试了将近 2-3 个小时来解决这个问题,但我没有足够的经验找到答案,我尝试了各种 IF 语句并研究了定义变量类型(即整数、浮点、字符等),但似乎都没有去工作。我相信一旦您知道解决方案就很简单,非常感谢您的帮助!

//Within this API we need to achieve collecting my data from Streak CRM us
//
//  Notes on Google API 
//      https://developers.google.com/apps-script/guides/services/external
//
//  Notes on Streak API
//    https://www.streak.com/api/
//
//API Key YOUR_API_KEY Here

function myStreak() {

//Google Sheet Data
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sheets = ss.getSheets();
  var sheet = ss.getSheetByName("StreakCRM"); 


//Streak API Call  
 var consumerKey = 'YOUR_API_KEY_HERE'
 var url = "https://www.streak.com/api/v1/boxes";  
 var headers = {
             "contentType": "application/json",
             "headers":{
"User-Agent": "MY_APP_NAME (App URL/your email address)",
               "Authorization": "Basic " + Utilities.base64Encode(consumerKey)
             },
             "validateHttpsCertificates" :false
             };

//Fetch Streak Data  
 var response = UrlFetchApp.fetch(url, headers);
 var dataAll = JSON.parse(response.getContentText());

//Write Captured Streak Data to Google Sheet  
 var dataSet = dataAll;  
 var rows = [],
  data; 

  for (i = 0; i < dataSet.length; i++) {
  data = dataSet[i];
  rows.push([data.name,
               data.stageKey,
//             data.fields['1001'], empty field
               data.fields['1002'],
               data.fields['1003'],
//             data.fields['1004'], empty field
               data.fields['1005'],
               data.fields['1006'],
               data.fields['1007'],
               data.fields['1008'],
               data.fields['1009'],
               data.fields['1010'],
               data.fields['1011'],
               data.fields['1012'],
//             data.fields['1013'], empty field
               data.fields['1014'],
               data.fields['1015'],
//             data.fields['1016'], empty field
               data.fields['1017'],
               data.fields['1018'],
               data.fields['1019'],
//             data.fields['1020'], empty field
               data.fields['1021'],
               data.fields['1023']]);//your JSON entities here
}

  dataRange = sheet.getRange(3, 1, rows.length, 19); // 19 Denotes total number of entites
  dataRange.setValues(rows);

//Capture response code success or errors
var text = response.getResponseCode();
Logger.log(text);
Logger.log(response);
}

这是预期的行为,因为这些属性在给定的数据行中完全缺失,因此它们是未定义的变量。当您将未定义的变量写入 sheet 时,它会转换为字符串 "undefined".

要处理这个问题,您应该检查每个 属性 名称以确保它存在,如果它不存在则使用所需的默认值。

您提到您尝试了各种 If 语句。检查一个值是否明确定义的方法是:

if(data.fields['somefieldname'] === undefined)

但是,通常您只想知道该值的计算结果是否为 false,在这种情况下您可以简单地执行以下操作:

if(data.fields['somefieldname'])

如果 data.fields['somefieldname'] 是任何计算结果为 false 的值,例如 nullfalse0undefined,对于任何其他值都是 true。

最后,由于 if 语句对于这种特殊用法来说有点长,我建议在您的代码中使用 "Conditional Operator" 或 "Ternary Operator" 来处理此问题:

   ( (data.fields['1002'])? data.fields['1002'] : '' )

可以理解为“如果data.fields['1002']为真,return data.fields['1002'],否则return空字符串"

这里有一些关于条件运算符的文档: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Conditional_Operator

在您的代码片段中,它看起来像这样:

rows.push([data.name,
               data.stageKey,
//             data.fields['1001'], empty field
               (data.fields['1002'])?data.fields['1002']:'',
               (data.fields['1003'])?data.fields['1002']:'',
               ...
               ...
            ]);

您可以为 "else" 条件指定任何值,例如 0 而不是空字符串。

你已经接受了一个很好的答案,但如果我能提供一个替代的修改方法。

//Write Captured Streak Data to Google Sheet  
  var dataSet = dataAll,
      rows = [],
      data,
      dataFields = ['name', 'stageKey', '1001' … ]; //include all the JSON fields you want to transfer including any deliberate blanks you don't exist. 

for (i = 0; i < dataSet.length; i++) {
  data = dataSet[i];

  rows.push(dataFields.map(function (f) {
    return data[f] || '';
  });
}

这里的重点是一开始就控制数据字段直接映射一次

在循环结束时,如果为了更好地考虑,您将看到另一种替代三元的方法。

return data[f] || '';

其中的形式

var foo = bar || 'default';

|| 是您从 if 语句中知道的 OR。实际上这个模式说“让 foo 成为 bar 除非它是 falsey 在这种情况下使用 'default'.