Как извлечь многослойный массив из JSON - PullRequest
0 голосов
/ 14 ноября 2018

У меня есть ответ 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"), заполнив следующие столбцы:

|Дата |Период |Топливо |Поколение |Емкость |Runtime |

Я предполагаю, что мне нужно написать что-то, что выдает (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 голосов
/ 14 ноября 2018

Как насчет этой модификации?Я думаю, что есть несколько решений для вашей ситуации.Поэтому, пожалуйста, подумайте об этом как об одном из них.

Точки модификации:

  • fuelData необходимо объявить в 1-м цикле for.
    • Это упоминается @ Slai.
  • iInput + rInput становится строковым типом.При этом возникает ошибка на appendRow().
    • iInput.concat(rInput) используется для этого.
  • Для того, чтобы установить значение | Date | Period | Fuel | Generation | Capacity | Runtime |, порядок нажатия значения должен составлять
  • rInput.push(fuelData[r].generation)
  • 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);

Ссылки:

Если это не то, что вы хотите, пожалуйста, скажите мне.Я хотел бы изменить его.

0 голосов
/ 14 ноября 2018

Вот альтернативный подход, который использует JSON.parse().

Функции Reviver являются необязательным параметром для JSON.parse().Крутая вещь в этих функциях заключается в том, что они вызываются парами ключ / значение для каждого узла в дереве объектов JSON с использованием поиска в глубину.

Запустите следующий фрагмент, чтобы понять, как это работает:

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":[{...}, {...},..], в котором он находится.

Вы можете использовать это для генерации необходимых данных для вашей электронной таблицы следующим образом:

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);

Приведенный выше фрагмент кода отфильтровывает нужные данные, когда реаниматор обходит дерево объектов JSON и заполняет массив двумерных значений в процессе.Теперь все, что вам нужно сделать, это вызвать setValues() на вашем листе с массивом значений.

0 голосов
/ 14 ноября 2018

Я думаю, что вы пропустили "genData [i]" в цикле for для var 'r'.Попробуйте это.

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);
  }
}

Также может быть, как вы храните ответ в классе вашей модели.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...