如何从json提取多层数组

时间:2018-11-14 06:32:17

标签: arrays json google-apps-script

我有一个类似于以下架构的JSON响应...

{
    "resultCode": 200,
    "message": "Success",
    "generated": "2018-11-14T18:42:02",
    "expires": "2018-11-14T18:50:00",
    "data": {
        "generationByFuel": [
            {
                "date": "2018-11-14T00:00:00",
                "period": 37,
                "generation": [
                    {
                        "fuel": "Hydro",
                        "generation": 1011.298,
                        "capacity": 2000
                    },
                    {
                        "fuel": "Wind",
                        "generation": 2544.788,
                        "capacity": 3500
                    }
                ]
            },
            {
                "date": "2018-11-14T00:00:00",
                "period": 36,
                "generation": [
                    {
                        "fuel": "Hydro",
                        "generation": 1100,
                        "capacity": 2000
                    },
                    {
                        "fuel": "Wind",
                        "generation": 2500,
                        "capacity": 3500
                    }
                ]
            }
        ]
    }
}

由此,我需要提取多个数组,并将其插入googlesheet(“ shtGen”)中,并填充以下各列:

|日期|期间|燃油|世代|容量运行时|

我猜我需要做的是写输出(generationByFuel[i](generation[r]))的东西,但我正在努力弄清楚该怎么做。

我尝试了许多选择,但以下是我认为自己走在正确轨道上的最后一次尝试。也就是说,该函数运行时不会返回错误,但不会在Google工作表中插入任何信息。当我使用调试器运行函数时,也会发生同样的事情。

// define output to paste into sheet
for (var i in genData) {
  var iInput = [];
  iInput.push(genData[i].date);
  iInput.push(genData[i].period);
  for (var r in fuelData) {
    var rInput = [];
    rInput.push(fuelData[r].fuel);
    rInput.push(fuelData[r].capacity);
    rInput.push(fuelData[r].generation);
    rInput.push(now = new Date());
    shtGen.appendRow(iInput + rInput);
  }
}

这里的任何帮助或建议将不胜感激。预先感谢!

3 个答案:

答案 0 :(得分:2)

此修改如何?我认为针对您的情况有几种解决方案。因此,请将此视为其中之一。

修改点:

    必须在第一个for循环中声明
  • fuelData
    • @Slai提到了这一点。
  • iInput + rInput成为字符串类型。这样,在appendRow()处发生错误。
    • iInput.concat(rInput)用于此。
  • 为了安排到| Date | Period | Fuel | Generation | Capacity | Runtime |,要求将值推入的顺序为
    1. rInput.push(fuelData[r].fuel)
    2. rInput.push(fuelData[r].generation)
    3. rInput.push(fuelData[r].capacity)

在此经过修改的脚本中,obj是您问题中的json对象。然后shtGen假设工作表对象。

修改后的脚本:

var obj = {### your json object ###};
var genData = obj.data.generationByFuel;
for (var i in genData) {
  var iInput = [];
  iInput.push(genData[i].date);
  iInput.push(genData[i].period);
  var fuelData = genData[i].generation; // Added
  for (var r in fuelData) {
    var rInput = [];
    rInput.push(fuelData[r].fuel); // Modified
    rInput.push(fuelData[r].generation); // Modified
    rInput.push(fuelData[r].capacity); // Modified
    rInput.push(new Date());
    shtGen.appendRow(iInput.concat(rInput)); // Modified
  }
}

我认为,当对象较大时,appendRow()成为处理成本增加的原因。因此,我建议如下使用setValues()将值放入电子表格。

var obj = {### your json object ###};
var res = [];
var genData = obj.data.generationByFuel;
for (var i in genData) {
  var iInput = [];
  iInput.push(genData[i].date);
  iInput.push(genData[i].period);
  var fuelData = genData[i].generation;
  for (var r in fuelData) {
    var rInput = [];
    rInput.push(fuelData[r].fuel);
    rInput.push(fuelData[r].generation);
    rInput.push(fuelData[r].capacity);
    rInput.push(new Date());
    res.push(iInput.concat(rInput)); // Modified
  }
}
shtGen.getRange(shtGen.getLastRow() + 1, 1, res.length, res[0].length).setValues(res); // Added

其他模式:

作为其他修改之一,您还可以使用以下脚本。该脚本的成本低于上述脚本的成本。

var obj = {### your json object ###};
var res = obj.data.generationByFuel.reduce(function(ar, e) {
  return ar.concat(e.generation.map(function(f) {
    return [e.date, e.period, f.fuel, f.generation, f.capacity, new Date()];
  }));
}, []);
shtGen.getRange(shtGen.getLastRow() + 1, 1, res.length, res[0].length).setValues(res);

参考文献:

如果这不是您想要的,请告诉我。我想修改它。

答案 1 :(得分:1)

这是利用JSON.parse()的另一种方法。

Reviver函数是JSON.parse()的可选参数。这些功能的妙处在于,它们使用深度优先搜索为JSON对象树中的每个节点使用键/值对进行调用。

运行以下代码片段以了解其工作原理:

{{ dropzone.config(custom_init='dz2 = this;document.getElementById("uploadID").addEventListener("click", function handler(e) {dz2.processQueue();});',
                     custom_options='autoProcessQueue: false, addRemoveLinks: true, maxFiles: 2,DROPZONE_UPLOAD_ACTION:handle_upload2,') }}

由以上脚本生成的控制台日志“深度优先”遍历对象树;在打印父节点的值之前,它将向下钻取以打印出叶节点的值。例如:var jsonString = JSON.stringify({ "resultCode": 200, "message": "Success", "generated": "2018-11-14T18:42:02", "expires": "2018-11-14T18:50:00", "data": { "generationByFuel": [ { "date": "2018-11-14T00:00:00", "period": 37, "generation": [ { "fuel": "Hydro", "generation": 1011.298, "capacity": 2000 }, { "fuel": "Wind", "generation": 2544.788, "capacity": 3500 } ] }, { "date": "2018-11-14T00:00:00", "period": 36, "generation": [ { "fuel": "Hydro", "generation": 1100, "capacity": 2000 }, { "fuel": "Wind", "generation": 2500, "capacity": 3500 } ] } ] } }); JSON.parse(jsonString, function(key, value) { console.log("Key:%s, Value:%o", key, value); return value; });在包含它的"fuel":"Hydro"数组之前打印。

您可以利用它为电子表格生成必要的数据,如下所示:

"generation":[{...}, {...},..]

上面的代码段在reviver遍历JSON的对象树并填充2D values数组的过程中过滤出所需的数据。现在,您要做的就是使用值数组在工作表上调用var jsonString = JSON.stringify({ "resultCode": 200, "message": "Success", "generated": "2018-11-14T18:42:02", "expires": "2018-11-14T18:50:00", "data": { "generationByFuel": [ { "date": "2018-11-14T00:00:00", "period": 37, "generation": [ { "fuel": "Hydro", "generation": 1011.298, "capacity": 2000 }, { "fuel": "Wind", "generation": 2544.788, "capacity": 3500 } ] }, { "date": "2018-11-14T00:00:00", "period": 36, "generation": [ { "fuel": "Hydro", "generation": 1100, "capacity": 2000 }, { "fuel": "Wind", "generation": 2500, "capacity": 3500 } ] } ] } }); var values = []; var state = {}; JSON.parse(jsonString, function(key, value) { switch(key) { case "generation": if (Array.isArray(value)) break; case "date": case "period": case "fuel": case "capacity": state[key] = value; break; } if (key === "capacity") { values.push([ state.date, state.period, state.fuel, state.generation, state.capacity, new Date() ]); } return value; }); console.log(values);

答案 2 :(得分:0)

我认为您错过了var'r'for循环中的“ genData [i]”。试试这个。

for (var i in genData) {
  var iInput = [];
  iInput.push(genData[i].date);
  iInput.push(genData[i].period);
  for (var r in fuelData) {
    var rInput = [];
    rInput.push(genData[i].fuelData[r].fuel);
    rInput.push(genData[i].fuelData[r].capacity);
    rInput.push(genData[i].fuelData[r].generation);
    rInput.push(now = new Date());
    shtGen.appendRow(iInput + rInput);
  }
}

这也可能是您将响应存储在模型类中的方式。