Как сделать цикл для файла JSON в узле JS - PullRequest
0 голосов
/ 16 июня 2019

Я пытаюсь получить массив объектов JSON с циклом for, но по какой-то причине он работает, только если я передаю индекс явно как число (например, parseJSON.sites[0]). Если я использую переменную, которую я предпочел бы в этом примере из-за цикла, показанный пример не работает.

let openJSON = fs.readFileSync('./pages/jsons/main.json', 'utf-8');
let parseJSON = JSON.parse(openJSON);
for (let i = 0; i <= 4; i++) {
    //this code doens't work and return: Cannot read property 'name' of undefined          
    main.push(parseJSON.sites[i]["name"]);

    //this code works, and returns what i expected
    main.push(parseJSON.sites[0]["name"]);
}


//main.json
{
    "sites": [
        { "name": "stackoverflow", "url": "stackoverflow.com" },
        { "name": "Youtube", "url": "www.youtube.com" },
    ]
}

Понятия не имею, почему этот код не работает. Я уже пытался изменить имя переменной i, в случае какого-либо конфликта, но он по-прежнему возвращает ту же ошибку. Я также попытался выполнить фрагмент кода без метода .push().

1 Ответ

2 голосов
/ 17 июня 2019

Проблема здесь, очевидно, в петле. В то время как массив sites в вашем объекте JSON из файла main.json содержит только две записи, ваш цикл выполняет четыре итерации. Это означает, что интерпретатор JavaScript (имейте в виду, что он интерпретируется во время выполнения) выдает ошибку в третьем цикле, где он не может найти никакого свойства name для третьего элемента в массиве sites, поскольку третьего элемента просто нет ( т.е. объект JSON).

Решение 1: Вы можете ограничить итерации цикла значением length массива sites, изменив условие цикла for следующим образом:

let main = []
let openJSON = fs.readFileSync('./main.json', 'utf-8');
let parseJSON = JSON.parse(openJSON);

for(let i = 0; i < parseJSON.sites.length; i++){ 
    main.push(parseJSON.sites[i]["name"]);
}

Решение 2: Если количество итераций должно оставаться на фиксированной длине (например, 4, как в вашем примере), вы можете отследить ошибку с помощью блока try-catch. Посмотрите пример ниже.

let main = []
let openJSON = fs.readFileSync('./main.json', 'utf-8');
let parseJSON = JSON.parse(openJSON);

for(let i = 0; i <= 4; i++){ 
    try {
      main.push(parseJSON.sites[i]["name"]);
    } catch (TypeError) {
      // handle TypeError
      console.log(`No property 'name' found for entry at index ${i}`)    
    }
}

Решение 3: Пока работает решение try-catch (то есть решение 2), оно может быть слишком большим для данного сценария, как указано в Julian . Поэтому я включил следующее решение, которое проверяет, есть ли в массиве sites по индексу i запись или undefined. Обратите внимание, что я включил две возможности в это решение.

let main = []
let openJSON = fs.readFileSync('./main.json', 'utf-8');
let parseJSON = JSON.parse(openJSON);

for(let i = 0; i <= 4; i++){
    // declare current entry (for readability)
    const currEntry = parseJSON.sites[i]

    // checking if there is an i-th entry in sites
    if (currEntry) {
      main.push(currEntry["name"]);
    }

    // same solution, more compact approach
    currEntry ? main.push(currEntry["name"]) : null
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...