【问题标题】:Parsing Keenio Extraction API query data into google spreadsheet将 Keenio 提取 API 查询数据解析为谷歌电子表格
【发布时间】:2018-06-24 10:37:44
【问题描述】:

如何解析这样的 JSON?这是要提取到 Google 电子表格中的 Keenio 提取 API 查询数据。

我尝试使用以下代码解析返回的 JSON,但不知道如何访问嵌套对象和数组。

function myFunction() {
  var URL = "https://api.keen.io/3.0/projects/" + 
    PROJECT_KEY + "/queries/extraction?api_key=" + 
    API_KEY + "&event_collection=" + 
    EVT_COL + "&timezone=" + 
    TIMEZONE + "&latest=" + 
    LATEST + "&property_names.........."

  var response = UrlFetchApp.fetch(URL);
  var json = response.getContentText();
  var rawdata = JSON.parse(response.getContentText());
  Logger.log(rawdata.result);
  var data = [];
  data.push(rawdata.result);
  SpreadsheetApp.getActiveSheet().appendRow(data);
}

上面我写了一个简单的函数来解析这个 JSON,但是我无法使用点符号来获取嵌套的对象和数组。

我在使用著名的 IMPORTJSON 代码时观察到的另一件事是,每次出现的列顺序都是打乱的,所以我在返回的数据上编写的公式会导致引用错误。

{
  "result": [
    {
      "sg_event_id": "92-OndRfTs6fZjNdHWzLBw",
      "timestamp": 1529618395,
      "url": "https://noname.com?utm_campaign=website&utm_source=sendgrid.com&utm_medium=email",
      "ip": "192.168.1.1",
      "event": "click",
      "keen": {
        "timestamp": "2018-06-21T21:59:55.000Z",
        "created_at": "2018-06-21T22:00:28.532Z",
        "id": "555c1f7c5asdf7000167d87b"
      },
      "url_offset": {
        "index": 38,
        "type": "text"
      },
      "sg_message_id": "F5mwV1rESdyKFA_2bn1IEQ.filter0042p3las1-15933-5B2A68E8-36.0",
      "useragent": "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)",
      "email": "no.name@noname.com"
    }, {
      "sg_event_id": "bjMlfsSfRyuXEVy8LndsYA",
      "timestamp": 1529618349,
      "url": "https://noname.com?utm_campaign=website&utm_source=sendgrid.com&utm_medium=email",
      "ip": "192.168.1.1",
      "event": "click",
      "keen": {
        "timestamp": "2018-06-21T21:59:09.000Z",
        "created_at": "2018-06-21T21:59:39.491Z",
        "id": "555c1f7c5asdf7000167d87b"
      },
      "url_offset": {
        "index": 36,
        "type": "text"
      },
      "sg_message_id": "F5mwV1rESdyKFA_2bn1IEQ.filter0042p3las1-15933-5B2A68E8-36.0",
      "useragent": "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)",
      "email": "no.name@noname.com"
    }, {
      "sg_event_id": "fru_s2s1RtueuqBMNoIoTg",
      "timestamp": 1529618255,
      "url": "https://noname.com?utm_campaign=website&utm_source=sendgrid.com&utm_medium=email",
      "ip": "192.168.1.1",
      "event": "click",
      "keen": {
        "timestamp": "2018-06-21T21:57:35.000Z",
        "created_at": "2018-06-21T21:58:20.374Z",
        "id": "555c1f7c5asdf7000167d87b"
      },
      "url_offset": {
        "index": 29,
        "type": "text"
      },
      "sg_message_id": "F5mwV1rESdyKFA_2bn1IEQ.filter0042p3las1-15933-5B2A68E8-36.0",
      "useragent": "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)",
      "email": "no.name@noname.com"
    }
  ]
}

【问题讨论】:

标签: json google-apps-script google-sheets sendgrid keen-io


【解决方案1】:

您提供的 JSON 数据由具有单个属性 result 的对象组成。 result 包含一个对象数组,每个对象代表一个具有字段->值属性的记录。

在您的函数中,您将创建一个 row 数组并将整个 result 数组作为数组的单个元素推送。

在表格中,一行由一个数组表示,每个单元格一个元素。

您需要处理result 数组并将每个元素从具有field->value 属性的对象转换为每个元素具有一个字段值的数组。

这是一个开始:

var rawdata = JSON.parse(json);

// Flatten each record.
for (var i = 0; i < rawdata.result.length; i++) {
  rawdata.result[i] = flatten(rawdata.result[i]);  
}

// Extract headers by scanning all results.
var headers = [];
for (var i = 0; i < rawdata.result.length; i ++) {
  for (var field in rawdata.result[i]) {
    if (!rawdata.result[i].hasOwnProperty(field)) continue; 
    if (headers.indexOf(field) > -1) continue;
    headers.push(field);
  }
}
headers.sort();

// Will contain an array of row arrays.
var data = [];
data.push(headers);

// Convert each result object into a row array and append to output.
for (var i = 0; i < rawdata.result.length; i++) {
  var row = [];
  for (var j = 0; j < headers.length; j++) {
    if (!rawdata.result[i].hasOwnProperty(headers[j])) {
      row.push("");
    } else {
      row.push(rawdata.result[i][headers[j]]);
    }
  }
  data.push(row);
}

这是flatten()的实现:

function flatten(obj, opt_prefix) {
  if (typeof obj !== 'object' || obj === null) {
    Logger.log(obj);
    throw "Cannot flatten non-object";
  }
  var prefix = opt_prefix ? opt_prefix + '.' :  '';
  var result = {};
  for (var k in obj) {
    if (!obj.hasOwnProperty(k)) continue;
    if (typeof obj[k] === 'object') {
      var nested = flatten(obj[k], k);
      for (var n in nested) {
        if (!nested.hasOwnProperty(n)) continue;
        result[prefix + n] = nested[n];
      }
      continue;
    }
    result[prefix + k] = obj[k];
  }
  return result;
}

此实现仅展平嵌套对象。如果存在嵌套数组,则会导致执行失败。它适用于您的示例数据,因为不存在嵌套数组。

另请注意,在 Javascript 中,对象的属性是无序的。如果您想对它们进行排序,您需要在代码中进行排序(例如,请参阅headers.sort() 调用)、如果字段名称已知则预定义顺序或两者的组合。

【讨论】:

  • 嗨@chuckx 试过你的代码。记录器.log(数据);显示数据...我添加了 SpreadsheetApp.openById("xxxxxxxx").getSheetByName("Sheet1").appendRow(data); 。得到这个错误 [Ljava.lang.Object; @536ef384 [Ljava.lang.Object;@9aebd75 [Ljava.lang.Object;@7003ecba,每列3列......
  • 在我的示例中,您最终会得到一个二维数组(即行列表)。 Sheet.appendRow() 占用一行。因此,您要么需要遍历行并一一添加它们,要么使用Sheet.getRange(row, column, numRows, numColumns) 获得适当大小的范围,然后调用Range.setValues(data)
  • 谢谢。此代码 ** var sht = SpreadsheetApp.openById("xxxxxxxx").getSheetByName("Sheet1"); data = data.map(function(v, i, data){ sht.appendRow(v); }); ** 现在工作。顺便说一句,有一个嵌套的 Keen 对象。我如何解析它以获得额外的列,例如 Keen_id、Keen_timestamp、Keen_created_at 等。大声思考,嵌套属性可能是对象或数组...
  • 日期似乎也有问题...有些显示为例如 1529618395 而嵌套的 Keen 对象中的日期显示例如timestamp=2018-06-21T21:59:55.000Z.
  • 关于时间戳,这些是 JSON 中的值。从第一条记录开始,"timestamp": 1529618395"keen": { "timestamp": "2018-06-21T21:59:09.000Z"。如果您想以某种方式更改它们,则需要指定您要查找的内容。
猜你喜欢
  • 1970-01-01
  • 2021-03-23
  • 2016-05-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-20
  • 1970-01-01
相关资源
最近更新 更多