Вывести JSON в таблицу при помощи JS

Необходимо вывести данные из JSON в виде таблицы. Вроде делаю все правильно но дохожу до массива с размерами и впадаю в ступор. Что я делаю не так? Как вытаскивать данные из вложенных объектов по индексу?

let data = {
  "2001": {
    "name": "Товар 1",
    "color": {
      "name": "Красный",
      "value": "#FF004D"
    },
    "sizes": {
      "3001": {
        "name": "S",
        "available": 26,
        "price": 900
      },
      "3002": {
        "name": "M",
        "available": 24,
        "price": 940
      },
      "3003": {
        "name": "L",
        "available": 12,
        "price": 300
      },
      "3004": {
        "name": "XL",
        "available": 32,
        "price": 800
      }
    }
  },
  "2002": {
    "name": "Товар 2",
    "color": {
      "name": "Зеленый",
      "value": "#008365"
    },
    "sizes": {
      "4001": {
        "name": "M",
        "available": 9998,
        "price": 200
      },
      "4002": {
        "name": "L",
        "available": 45,
        "price": 230
      },
      "4003": {
        "name": "XXL",
        "available": 1,
        "price": 1300
      }
    }
  },
  "2003": {
    "name": "Товар 3",
    "color": {
      "name": "Синий",
      "value": "#3B5998"
    },
    "sizes": {
      "5001": {
        "name": "S",
        "available": 0,
        "price": 0
      },
      "5002": {
        "name": "M",
        "available": 0,
        "price": 0
      },
      "5003": {
        "name": "L",
        "available": 23,
        "price": 130
      }
    }
  },
  "2004": {
    "name": "Товар 4",
    "color": {
      "name": "Марсала",
      "value": "#4C1A2C"
    },
    "sizes": {
      "6001": {
        "name": "L",
        "available": 0,
        "price": 0
      },
      "6002": {
        "name": "XL",
        "available": 0,
        "price": 0
      },
      "6003": {
        "name": "XXL",
        "available": 0,
        "price": 0
      }
    }
  }
}

for (let key in data) {
  let row = document.createElement('tr')
  row.innerHTML = `<td>${data[key].name}</td>`
  document.querySelector('.product').appendChild(row)
  for (let j = 0; j < Object.keys(data).length; j++) {
    let row = document.createElement('tr')
    row.innerHTML = `
        <td>${data[key].name}</td>
        <td>${data[key].color.name}</td>
        <td>${data[key].sizes}</td>
        `
    document.querySelector('.product').appendChild(row)

  }
}
<!doctype html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, 
    minimum-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>

<body>
  <div class="container">
    <table class="product">
      <tr>
        <th>Название товара</th>
        <th>Цвет</th>
        <th>Размер</th>
        <th>Доступное кол-во</th>
        <th>Цена</th>
      </tr>
    </table>
  </div>
  <script src="script.js"></script>
</body>

</html>


Ответы (2 шт):

Автор решения: Денис Соснин
for (key in data) {
 for (key2 in data[key].sizes){
     let row = document.createElement('tr')
     row.innerHTML = `<td>${data[key].name}</td>
                      <td>${data[key].color.name}</td>
                      <td>${data[key].sizes[key2].name}</td>
                      <td>${data[key].sizes[key2].available}</td>
                      <td>${data[key].sizes[key2].price}</td>
                     `
     document.querySelector('.product').appendChild(row)
     console.log(data[key].sizes[key2].name);
 }
 }
→ Ссылка
Автор решения: yar85

const tbody = document.querySelector('.product').tBodies[0],
      szKeys = ['name', 'available', 'price'],
      data = getData();

Object.values(data).forEach(({ name, color: { name: color }, sizes }) => {  // получение значений объекта, и цикл по ним - с деструктуризацией каждого значения (объекта товара) из первого аргумента коллбэка
  const szData = szKeys.reduce((rslt, k) => ((rslt[k] = []), rslt), {});    // инициализация нового объекта под данные о размерах (пустыми массивами)
  Object.values(sizes).forEach(size => {
    szKeys.forEach(key => szData[key].push(size[key]));                     // значения свойств каждого размера заносим в объект с данными о размерах
  });
  const [ sizeNames, qtys, prices ] = Object.values(szData).map(arr => arr.join('/')),    // объединение (в строку) каждого массива данных о размерах, и затем присваивание полученных строк переменным
        row = tbody.insertRow();                                                          // добавление новой строки таблицы
  [name, color, sizeNames, qtys, prices].forEach(v => row.insertCell().textContent = v);  // добавление в строку таблицы новых ячеек, и их заполнение значениями из массива
});


function getData() {
  return {
    "2001": {
      "name": "Товар 1",
      "color": {
        "name": "Красный",
        "value": "#FF004D"
      },
      "sizes": {
        "3001": {
          "name": "S",
          "available": 26,
          "price": 900
        },
        "3002": {
          "name": "M",
          "available": 24,
          "price": 940
        },
        "3003": {
          "name": "L",
          "available": 12,
          "price": 300
        },
        "3004": {
          "name": "XL",
          "available": 32,
          "price": 800
        }
      }
    },
    "2002": {
      "name": "Товар 2",
      "color": {
        "name": "Зеленый",
        "value": "#008365"
      },
      "sizes": {
        "4001": {
          "name": "M",
          "available": 9998,
          "price": 200
        },
        "4002": {
          "name": "L",
          "available": 45,
          "price": 230
        },
        "4003": {
          "name": "XXL",
          "available": 1,
          "price": 1300
        }
      }
    },
    "2003": {
      "name": "Товар 3",
      "color": {
        "name": "Синий",
        "value": "#3B5998"
      },
      "sizes": {
        "5001": {
          "name": "S",
          "available": 0,
          "price": 0
        },
        "5002": {
          "name": "M",
          "available": 0,
          "price": 0
        },
        "5003": {
          "name": "L",
          "available": 23,
          "price": 130
        }
      }
    },
    "2004": {
      "name": "Товар 4",
      "color": {
        "name": "Марсала",
        "value": "#4C1A2C"
      },
      "sizes": {
        "6001": {
          "name": "L",
          "available": 0,
          "price": 0
        },
        "6002": {
          "name": "XL",
          "available": 0,
          "price": 0
        },
        "6003": {
          "name": "XXL",
          "available": 0,
          "price": 0
        }
      }
    }
  };
}
table  { border-collapse: collapse; }
th, td { padding: 0.2em 0.4em; border: 1px solid #ccc; }
<!doctype html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, 
    minimum-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>

<body>
  <div class="container">
    <table class="product">
      <tr>
        <th>Название товара</th>
        <th>Цвет</th>
        <th>Размер</th>
        <th>Доступное кол-во</th>
        <th>Цена</th>
      </tr>
    </table>
  </div>
  <script src="script.js"></script>
</body>

</html>

Распределение по столбцам и строкам (в цикле по Object.values(sizes)) - может быть каким угодно, тут для примера я просто объединил полученные значения в текстовом содержимом ячеек.
Советую развернуть кодсниппет на всю страницу, чтобы лучше видеть комментарии в строках.


MDN:

  • Деструктуризация в JS;
  • DOM-методы таблицы: insertRow (для добавления строк, tr); и insertCell (для добавления ячеек, th|td);
  • Статический метод Object.values возвращающий (массивом) значения всех собственных свойств объекта.
→ Ссылка