HTML Diff
3 added 3 removed
Original 2026-01-01
Modified 2026-02-21
1 <p>У языка гипертекстовой разметки веб-страниц <a>HTML</a>и формата данных <a>JSON</a>есть общая черта: оба они помогают структурировать информацию, хотя в веб-разработке их используют для разных задач. HTML необходим для отображения разметки сайтов, а JSON - для обмена данными с сервером.</p>
1 <p>У языка гипертекстовой разметки веб-страниц <a>HTML</a>и формата данных <a>JSON</a>есть общая черта: оба они помогают структурировать информацию, хотя в веб-разработке их используют для разных задач. HTML необходим для отображения разметки сайтов, а JSON - для обмена данными с сервером.</p>
2 <p>То есть, отправляя с сервера информацию в формате JSON, мы делаем её независимой от формата отображения на устройстве пользователя: он может листать экраны нативного мобильного приложения (где не используется HTML), запрашивать данные из консольной утилиты или смотреть в браузере. Да и для отображения в браузере подчас нужна "многоэтажная" JavaScript-логика, которую в сгенерированный сервером HTML просто не упаковать.</p>
2 <p>То есть, отправляя с сервера информацию в формате JSON, мы делаем её независимой от формата отображения на устройстве пользователя: он может листать экраны нативного мобильного приложения (где не используется HTML), запрашивать данные из консольной утилиты или смотреть в браузере. Да и для отображения в браузере подчас нужна "многоэтажная" JavaScript-логика, которую в сгенерированный сервером HTML просто не упаковать.</p>
3 <p>Вообще, библиотеки для работы с JSON есть практически в любом современном языке программирования, то есть это универсальный формат. Однако сама аббревиатура JSON изначально является сокращением от JavaScript Object Notation, а потому в JS есть встроенные методы для работы с JSON. Кроме того, вид данных в последнем почти идентичен синтаксису <a>объектов</a>в JavaScript. То есть JavaScript идеально поддерживает свой "дочерний" формат.</p>
3 <p>Вообще, библиотеки для работы с JSON есть практически в любом современном языке программирования, то есть это универсальный формат. Однако сама аббревиатура JSON изначально является сокращением от JavaScript Object Notation, а потому в JS есть встроенные методы для работы с JSON. Кроме того, вид данных в последнем почти идентичен синтаксису <a>объектов</a>в JavaScript. То есть JavaScript идеально поддерживает свой "дочерний" формат.</p>
4 <p>Итак, многие веб-разработчики предпочитают выдавать по запросу с фронтенда HTML-код, упакованный в JSON, и уже в браузере конвертировать его в обычную HTML-разметку. Так работает и наш сайт -<a>Skillbox Media</a>(мы анализировали это в <a>статье</a>о парсинге данных).</p>
4 <p>Итак, многие веб-разработчики предпочитают выдавать по запросу с фронтенда HTML-код, упакованный в JSON, и уже в браузере конвертировать его в обычную HTML-разметку. Так работает и наш сайт -<a>Skillbox Media</a>(мы анализировали это в <a>статье</a>о парсинге данных).</p>
5 - JSON-ответ при подгрузке статей на страницу Skillbox Media "Код" (после нажатия кнопки "Показать ещё")<em>Скриншот: Skillbox Media</em><p>Такой же способ подгрузки дополнительных статей в рубриках отдельных стран реализован и на сайте организации "<a>Репортёры без границ</a>". Выберем случайную страну - пусть это будет<a>Италия</a>. При нажатии на кнопку Show more posts загружаются три более старых материала. Если перейти по ссылке в кнопке, то внутри элемента &lt;textarea&gt; мы увидим JSON-вставку с кодом статей:</p>
5 + JSON-ответ при подгрузке статей на страницу Skillbox Media "Код" (после нажатия кнопки "Показать ещё")<em>Скриншот: Skillbox Media</em><p>Такой же способ подгрузки дополнительного контента реализован на платформе Stack Overflow. Для примера откроем раздел<a>Newest Questions</a>. Если перейти на следующую страницу (например, на страницу 2), на сайте подгрузятся новые вопросы. А если открыть инструменты разработчика и перейти во вкладку Network, среди запросов вы увидите JSON-файлы с данными о вопросах:</p>
6 - JSON-ответ при подгрузке статей в рубриках стран на сайте организации "Репортёры без границ" (первая часть работы)<em>Скриншот: Skillbox Media</em>JSON-ответ при подгрузке статей в рубриках стран на сайте организации "Репортёры без границ" (вторая часть работы)<em>Скриншот: Skillbox Media</em><p>Произвести конвертацию HTML в JSON несложно, если знать особенности обоих форматов. Сначала мы кратко разберём эти особенности, а потом напишем небольшое приложение, которое будет конвертировать один формат в другой.</p>
6 + JSON-ответы сервера при переходе между страницами в разделе Newest Questions на сайте Stack Overflow<em>Скриншот: Skillbox Media</em><p>Произвести конвертацию HTML в JSON несложно, если знать особенности обоих форматов. Сначала мы кратко разберём эти особенности, а потом напишем небольшое приложение, которое будет конвертировать один формат в другой.</p>
7 <p>Вспомним, что<a>HTML-разметка</a>сайта состоит из элементов, которые, как правило, состоят из трёх частей: открывающий тег, закрывающий тег и контент:</p>
7 <p>Вспомним, что<a>HTML-разметка</a>сайта состоит из элементов, которые, как правило, состоят из трёх частей: открывающий тег, закрывающий тег и контент:</p>
8 &lt;p&gt;HTML vs. JSON&lt;/p&gt;<p>Внутри открывающего тега могут располагаться различные атрибуты в формате attribute="value":</p>
8 &lt;p&gt;HTML vs. JSON&lt;/p&gt;<p>Внутри открывающего тега могут располагаться различные атрибуты в формате attribute="value":</p>
9 &lt;p class="zag"&gt;HTML vs. JSON&lt;/p&gt;<p>JSON устроен иначе: он состоит из набора пар "ключ": "значение". Ключи и значения заключены в кавычки, после ключа следует двоеточие, пары разделены запятыми и упакованы внутрь круглых скобок.</p>
9 &lt;p class="zag"&gt;HTML vs. JSON&lt;/p&gt;<p>JSON устроен иначе: он состоит из набора пар "ключ": "значение". Ключи и значения заключены в кавычки, после ключа следует двоеточие, пары разделены запятыми и упакованы внутрь круглых скобок.</p>
10 <p>В качестве значений в JSON-разметке <a>могут</a>использоваться числа, строки, логические значения, объекты, массивы и null (нам далее пригодится знание этого факта, потому что мы будем создавать пример с объектами и массивами).</p>
10 <p>В качестве значений в JSON-разметке <a>могут</a>использоваться числа, строки, логические значения, объекты, массивы и null (нам далее пригодится знание этого факта, потому что мы будем создавать пример с объектами и массивами).</p>
11 { "key1": "value", "key2": "value" }<p>Последняя пара не отделяется запятой -<a>висящие запятые (trailing commas)</a>в JSON запрещены.</p>
11 { "key1": "value", "key2": "value" }<p>Последняя пара не отделяется запятой -<a>висящие запятые (trailing commas)</a>в JSON запрещены.</p>
12 <p>Кажется, что различия ощутимые, но это лишь на первый взгляд: на деле представить HTML-код в формате JSON относительно несложно, следите за руками:</p>
12 <p>Кажется, что различия ощутимые, но это лишь на первый взгляд: на деле представить HTML-код в формате JSON относительно несложно, следите за руками:</p>
13 &lt;p&gt;Совистика - это наука о совах.&lt;/p&gt;{ "p": "Совистика - это наука о совах." }<p>Любой HTML-элемент легко превращается в JSON-пару "ключ": "значение", где ключом выступает название элемента, а значением - его текстовое содержимое или вложенный элемент следующего уровня.</p>
13 &lt;p&gt;Совистика - это наука о совах.&lt;/p&gt;{ "p": "Совистика - это наука о совах." }<p>Любой HTML-элемент легко превращается в JSON-пару "ключ": "значение", где ключом выступает название элемента, а значением - его текстовое содержимое или вложенный элемент следующего уровня.</p>
14 <p>Теперь попробуем с помощью JavaScript сделать нечто подобное на примере одной страницы сайта.</p>
14 <p>Теперь попробуем с помощью JavaScript сделать нечто подобное на примере одной страницы сайта.</p>
15 <p>Процесс упаковки данных в JSON называется сериализацией, а обратный процесс - десериализацией. Перевести HTML-разметку в JSON можно двумя способами:</p>
15 <p>Процесс упаковки данных в JSON называется сериализацией, а обратный процесс - десериализацией. Перевести HTML-разметку в JSON можно двумя способами:</p>
16 <ul><li>Преобразовать разметку "в лоб", запихнув весь HTML-код в одну пару "ключ": "значение" - то есть как значение ключа &lt;html&gt;<em>, (как на скриншоте разметки Skillbox Media)</em>.</li>
16 <ul><li>Преобразовать разметку "в лоб", запихнув весь HTML-код в одну пару "ключ": "значение" - то есть как значение ключа &lt;html&gt;<em>, (как на скриншоте разметки Skillbox Media)</em>.</li>
17 <li>Написать более сложный вариант JSON, чтобы структура JSON-строки полностью соответствовала структуре HTML-документа.</li>
17 <li>Написать более сложный вариант JSON, чтобы структура JSON-строки полностью соответствовала структуре HTML-документа.</li>
18 </ul><p>Выбор способа будет зависеть от ваших задач. Мы же в образовательных целях разберём более сложный, второй способ - это позволит нам опробовать возможности языка JavaScript и сохранить структуру страницы. Возьмём для примера следующий код:</p>
18 </ul><p>Выбор способа будет зависеть от ваших задач. Мы же в образовательных целях разберём более сложный, второй способ - это позволит нам опробовать возможности языка JavaScript и сохранить структуру страницы. Возьмём для примера следующий код:</p>
19 &lt;!DOCTYPE html&gt; &lt;html&gt; &lt;head&gt; &lt;meta charset="utf-8"&gt; &lt;title&gt;Конвертация HTML в JSON&lt;/title&gt; &lt;/head&gt; &lt;body&gt; &lt;p class="myclass" style="margin: 1px;"&gt;Какой-то абзац.&lt;/p&gt; &lt;div&gt; &lt;p&gt;&lt;span&gt;Другой абзац (элемент 3-го уровня)&lt;/span&gt;&lt;/p&gt; &lt;span&gt;Другой абзац (элемент 2-го уровня)&lt;/span&gt; &lt;span&gt;&lt;a href="#"&gt;Какая-то ссылка (элемент 3-го уровня).&lt;/a&gt;&lt;/span&gt; &lt;img src="images/test.png" alt="Тестовое изображение"&gt; &lt;/div&gt; &lt;script src="script.js"&gt;&lt;/script&gt; &lt;/body&gt; &lt;/html&gt;<p>Здесь есть все базовые составляющие шаблона HTML-страницы: служебные элементы и контент в теле страницы. У некоторых элементов есть атрибуты и вложенные элементы, что тоже нужно учесть при конвертировании.</p>
19 &lt;!DOCTYPE html&gt; &lt;html&gt; &lt;head&gt; &lt;meta charset="utf-8"&gt; &lt;title&gt;Конвертация HTML в JSON&lt;/title&gt; &lt;/head&gt; &lt;body&gt; &lt;p class="myclass" style="margin: 1px;"&gt;Какой-то абзац.&lt;/p&gt; &lt;div&gt; &lt;p&gt;&lt;span&gt;Другой абзац (элемент 3-го уровня)&lt;/span&gt;&lt;/p&gt; &lt;span&gt;Другой абзац (элемент 2-го уровня)&lt;/span&gt; &lt;span&gt;&lt;a href="#"&gt;Какая-то ссылка (элемент 3-го уровня).&lt;/a&gt;&lt;/span&gt; &lt;img src="images/test.png" alt="Тестовое изображение"&gt; &lt;/div&gt; &lt;script src="script.js"&gt;&lt;/script&gt; &lt;/body&gt; &lt;/html&gt;<p>Здесь есть все базовые составляющие шаблона HTML-страницы: служебные элементы и контент в теле страницы. У некоторых элементов есть атрибуты и вложенные элементы, что тоже нужно учесть при конвертировании.</p>
20 - <p>Вернёмся к типичной ситуации, как на первых скриншотах: каркас страницы статичен, а при подгрузке с сервера меняется только тело, которое и нужно скормить JSON-конвертеру. Следовательно, нас интересует содержимое элемента &lt;body&gt;:</p>
20 + <p>Вернёмся к типичной ситуации, как на первых скриншотах: каркас страницы статичен, а при подгрузке с сервера меняется только тело, которое и нужн скормить JSON-конвертеру. Следовательно, нас интересует содержимое элемента &lt;body&gt;:</p>
21 &lt;p class="myclass" style="margin: 1px;"&gt;Какой-то абзац.&lt;/p&gt; &lt;div&gt; &lt;p&gt;&lt;span&gt;Другой абзац (элемент 3-го уровня)&lt;/span&gt;&lt;/p&gt; &lt;span&gt;Другой абзац (элемент 2-го уровня)&lt;/span&gt; &lt;span&gt;&lt;a href="#"&gt;Какая-то ссылка (элемент 3-го уровня).&lt;/a&gt;&lt;/span&gt; &lt;img src="images/test.png" alt="Тестовое изображение"&gt; &lt;/div&gt; &lt;script src="script.js"&gt;&lt;/script&gt;<p>Сейчас на странице несколько произвольных абзацев и картинка. Наш учебный конвертер будет почти универсальным и сможет упаковать в JSON эти и любые другие HTML-элементы в теле - вплоть до третьего уровня вложенности.</p>
21 &lt;p class="myclass" style="margin: 1px;"&gt;Какой-то абзац.&lt;/p&gt; &lt;div&gt; &lt;p&gt;&lt;span&gt;Другой абзац (элемент 3-го уровня)&lt;/span&gt;&lt;/p&gt; &lt;span&gt;Другой абзац (элемент 2-го уровня)&lt;/span&gt; &lt;span&gt;&lt;a href="#"&gt;Какая-то ссылка (элемент 3-го уровня).&lt;/a&gt;&lt;/span&gt; &lt;img src="images/test.png" alt="Тестовое изображение"&gt; &lt;/div&gt; &lt;script src="script.js"&gt;&lt;/script&gt;<p>Сейчас на странице несколько произвольных абзацев и картинка. Наш учебный конвертер будет почти универсальным и сможет упаковать в JSON эти и любые другие HTML-элементы в теле - вплоть до третьего уровня вложенности.</p>
22 <p>Алгоритм будет следующим:</p>
22 <p>Алгоритм будет следующим:</p>
23 <ul><li>Создадим JavaScript-объект для записи HTML-элементов, их атрибутов и содержимого.</li>
23 <ul><li>Создадим JavaScript-объект для записи HTML-элементов, их атрибутов и содержимого.</li>
24 <li>По очереди запишем в объект все элементы.</li>
24 <li>По очереди запишем в объект все элементы.</li>
25 <li>Преобразуем объект в JSON-формат.</li>
25 <li>Преобразуем объект в JSON-формат.</li>
26 </ul><p>Чуть ниже мы рассмотрим указанные шаги в деталях, но для начала нужно создать два файла:</p>
26 </ul><p>Чуть ниже мы рассмотрим указанные шаги в деталях, но для начала нужно создать два файла:</p>
27 <ul><li>Первый назовём "<a>HTML в JSON.html</a>" (по ссылке - содержимое файла на сервисе Pastebin) и поместим в него собственно страницу для преобразования.</li>
27 <ul><li>Первый назовём "<a>HTML в JSON.html</a>" (по ссылке - содержимое файла на сервисе Pastebin) и поместим в него собственно страницу для преобразования.</li>
28 <li>Второй будет называться "<a>script.js</a>" (по ссылке - содержимое файла на сервисе Pastebin) - в него мы вынесем написанный на JavaScript конвертер страницы в JSON.</li>
28 <li>Второй будет называться "<a>script.js</a>" (по ссылке - содержимое файла на сервисе Pastebin) - в него мы вынесем написанный на JavaScript конвертер страницы в JSON.</li>
29 </ul><p>Скрипт будет вызываться после загрузки нашей страницы, поэтому мы поместим в тело HTML-файла элемент &lt;script&gt; со ссылкой на JS-файл (см. первую вставку кода).</p>
29 </ul><p>Скрипт будет вызываться после загрузки нашей страницы, поэтому мы поместим в тело HTML-файла элемент &lt;script&gt; со ссылкой на JS-файл (см. первую вставку кода).</p>
30 <p>Теперь рассмотрим пошагово, как будет устроен наш конвертер в файле script.js.</p>
30 <p>Теперь рассмотрим пошагово, как будет устроен наш конвертер в файле script.js.</p>
31 function convertHTMLtoJSON() { // Тут будет конвертер }; // Выводим результат через секунду после загрузки исходной страницы setTimeout(convertHTMLtoJSON, 1000);<p>Сначала объявим функцию с понятным названием - "конвертер HTML в JSON". В её теле будет находиться конвертер. После объявления функции заложим её вызов с задержкой в одну секунду с помощью встроенного метода<a>setTimeout()</a>: таким образом, после открытия HTML-файла в браузере мы сначала увидим исходную страницу, а потом она сотрётся и заменится на JSON-строку.</p>
31 function convertHTMLtoJSON() { // Тут будет конвертер }; // Выводим результат через секунду после загрузки исходной страницы setTimeout(convertHTMLtoJSON, 1000);<p>Сначала объявим функцию с понятным названием - "конвертер HTML в JSON". В её теле будет находиться конвертер. После объявления функции заложим её вызов с задержкой в одну секунду с помощью встроенного метода<a>setTimeout()</a>: таким образом, после открытия HTML-файла в браузере мы сначала увидим исходную страницу, а потом она сотрётся и заменится на JSON-строку.</p>
32 <p>Теперь займёмся телом созданной функции и для красоты на каждом шаге её работы будем выводить понятные уведомления в консоль (скриншот с ними будет ниже). Начнём с этого:</p>
32 <p>Теперь займёмся телом созданной функции и для красоты на каждом шаге её работы будем выводить понятные уведомления в консоль (скриншот с ними будет ниже). Начнём с этого:</p>
33 // Очистка консоли для повторного запуска примера console.clear(); // Показ в консоли названия программы console.log('= КОНВЕРТЕР HTML В JSON ='); // Уведомление в консоль о начале работы конвертера console.log('НАЧАТА СЕРИАЛИЗАЦИЯ HTML-КОДА.');<p>Результаты поиска элементов, их атрибутов и содержимого также будут сопровождаться уведомлениями, чтобы мы не пропустили ничего важного.</p>
33 // Очистка консоли для повторного запуска примера console.clear(); // Показ в консоли названия программы console.log('= КОНВЕРТЕР HTML В JSON ='); // Уведомление в консоль о начале работы конвертера console.log('НАЧАТА СЕРИАЛИЗАЦИЯ HTML-КОДА.');<p>Результаты поиска элементов, их атрибутов и содержимого также будут сопровождаться уведомлениями, чтобы мы не пропустили ничего важного.</p>
34 <p>Мы уже упоминали, что формат JSON похож на объекты в JavaScript. Именно поэтому, следуя алгоритму, создадим объект и запишем в него HTML-элементы.</p>
34 <p>Мы уже упоминали, что формат JSON похож на объекты в JavaScript. Именно поэтому, следуя алгоритму, создадим объект и запишем в него HTML-элементы.</p>
35 let objectToStringify = new Object(); // Создаём объект для записи элементов и их контента (в конце объект будет преобразован в JSON)<p>После создания объекта начинается главное: цикл перебора и записи элементов и содержимого в объект, и тут самое время поговорить о том, что конкретно мы хотим в итоге получить.</p>
35 let objectToStringify = new Object(); // Создаём объект для записи элементов и их контента (в конце объект будет преобразован в JSON)<p>После создания объекта начинается главное: цикл перебора и записи элементов и содержимого в объект, и тут самое время поговорить о том, что конкретно мы хотим в итоге получить.</p>
36 <p>Структура JSON-результата будет такой: название элемента первого уровня, потом его атрибуты, затем его содержимое - вложенные элементы или текст. Если содержимое - это вложенные элементы, то внутри будут их названия, атрибуты и содержимое (также вложенные элементы или текст). Каждая часть структуры будет иметь порядковый номер - начиная с нуля - и указание на уровень элемента.</p>
36 <p>Структура JSON-результата будет такой: название элемента первого уровня, потом его атрибуты, затем его содержимое - вложенные элементы или текст. Если содержимое - это вложенные элементы, то внутри будут их названия, атрибуты и содержимое (также вложенные элементы или текст). Каждая часть структуры будет иметь порядковый номер - начиная с нуля - и указание на уровень элемента.</p>
37 <p>К примеру, первый элемент в теле нашей страницы после перевода в JSON должен принять такой вид:</p>
37 <p>К примеру, первый элемент в теле нашей страницы после перевода в JSON должен принять такой вид:</p>
38 { "element0Level1 (порядковый номер 1-го элемента 1-го уровня)": [ { "element0Level1Name (название этого элемента 1-го уровня)": "P" }, { "element0Level1Attributes (атрибуты этого элемента 1-го уровня)": [ { "element0Level1attribute0 (первый атрибут этого элемента 1-го уровня)": [ { "element0Level1attribute0Name (название первого атрибута)": "class" }, { "element0Level1attribute0Value (значение первого атрибута)": "myclass" } ] }, { "element0Level1attribute1 (второй атрибут этого элемента 1-го уровня)": [ { "element0Level1attribute1Name (название второго атрибута)": "style" }, { "element0Level1attribute1Value (значение второго атрибута)": "margin: 1px;" } ] } ] }, { "element0Level1Content (содержимое этого элемента 1-го уровня, в данном случае текст)": "Какой-то абзац." } ], }<p>Переводим на человеческий язык: "элемент 0 (то есть первый - у программистов своя математика) первого уровня, имя P, есть атрибуты. Атрибут 1 class="myclass", атрибут 2 style="margin: 1px;". Содержит текст "Какой-то абзац“".</p>
38 { "element0Level1 (порядковый номер 1-го элемента 1-го уровня)": [ { "element0Level1Name (название этого элемента 1-го уровня)": "P" }, { "element0Level1Attributes (атрибуты этого элемента 1-го уровня)": [ { "element0Level1attribute0 (первый атрибут этого элемента 1-го уровня)": [ { "element0Level1attribute0Name (название первого атрибута)": "class" }, { "element0Level1attribute0Value (значение первого атрибута)": "myclass" } ] }, { "element0Level1attribute1 (второй атрибут этого элемента 1-го уровня)": [ { "element0Level1attribute1Name (название второго атрибута)": "style" }, { "element0Level1attribute1Value (значение второго атрибута)": "margin: 1px;" } ] } ] }, { "element0Level1Content (содержимое этого элемента 1-го уровня, в данном случае текст)": "Какой-то абзац." } ], }<p>Переводим на человеческий язык: "элемент 0 (то есть первый - у программистов своя математика) первого уровня, имя P, есть атрибуты. Атрибут 1 class="myclass", атрибут 2 style="margin: 1px;". Содержит текст "Какой-то абзац“".</p>
39 <p>element0Level1 - это ключ первой пары "ключ": "значение", а всё остальное - содержимое значения этой пары, которое представляет собой массив вложенных объектов - объекта с названием элемента, объекта со всеми атрибутами и объекта с содержимым.</p>
39 <p>element0Level1 - это ключ первой пары "ключ": "значение", а всё остальное - содержимое значения этой пары, которое представляет собой массив вложенных объектов - объекта с названием элемента, объекта со всеми атрибутами и объекта с содержимым.</p>
40 <p>Следующие элементы 1-го уровня будут упакованы в такие же пары, а элементы 2-го и 3-го уровней повторят ту же структуру во вложениях. Короче, у нас чередуются объекты, вложенные массивы и вложенные в них объекты.</p>
40 <p>Следующие элементы 1-го уровня будут упакованы в такие же пары, а элементы 2-го и 3-го уровней повторят ту же структуру во вложениях. Короче, у нас чередуются объекты, вложенные массивы и вложенные в них объекты.</p>
41 Простое объяснение работы JSON-конвертера<em>Кадр: сериал "В Филадельфии всегда солнечно"</em><p>Теперь, когда мы представили себе результат, разберём реализацию. Цикл перебора HTML-элементов должен разобрать их на кусочки - как детальки лего. Находить составляющие элементов помогут следующие свойства:</p>
41 Простое объяснение работы JSON-конвертера<em>Кадр: сериал "В Филадельфии всегда солнечно"</em><p>Теперь, когда мы представили себе результат, разберём реализацию. Цикл перебора HTML-элементов должен разобрать их на кусочки - как детальки лего. Находить составляющие элементов помогут следующие свойства:</p>
42 <ul><li><a>tagName</a>найдёт названия элементов;</li>
42 <ul><li><a>tagName</a>найдёт названия элементов;</li>
43 <li><a>attributes</a>отдаст коллекцию атрибутов элемента, а обращения к attributes.name и attributes.value вернут названия и значения отдельных атрибутов;</li>
43 <li><a>attributes</a>отдаст коллекцию атрибутов элемента, а обращения к attributes.name и attributes.value вернут названия и значения отдельных атрибутов;</li>
44 <li>для получения вложенных элементов любого уровня и текста понадобятся свойства <a>children</a>и <a>textContent</a>соответственно.</li>
44 <li>для получения вложенных элементов любого уровня и текста понадобятся свойства <a>children</a>и <a>textContent</a>соответственно.</li>
45 </ul><p>На каждом из уровней вложенности HTML-элементов мы сначала будем измерять их количество, а потом перебирать с помощью цикла for.</p>
45 </ul><p>На каждом из уровней вложенности HTML-элементов мы сначала будем измерять их количество, а потом перебирать с помощью цикла for.</p>
46 // Оценка HTML-элементов 1-го уровня let bodyElemsLength = document.body.children.length; // Считаем количество элементов в body<p>Здесь и далее считаем количество HTML-элементов или атрибутов с помощью свойства<a>length</a>.</p>
46 // Оценка HTML-элементов 1-го уровня let bodyElemsLength = document.body.children.length; // Считаем количество элементов в body<p>Здесь и далее считаем количество HTML-элементов или атрибутов с помощью свойства<a>length</a>.</p>
47 // Перебор всех HTML-элементов 1-го уровня for (let e = 0; e &lt; bodyElemsLength; e++) {<p>Название переменной e - это просто понятное сокращение от "element". Вы же можете выбрать любое, на свой вкус.</p>
47 // Перебор всех HTML-элементов 1-го уровня for (let e = 0; e &lt; bodyElemsLength; e++) {<p>Название переменной e - это просто понятное сокращение от "element". Вы же можете выбрать любое, на свой вкус.</p>
48 <p>Самое простое - записать названия элементов. Для этого обращаемся к коллекции потомков элемента &lt;body&gt; и перебираем их, подставляя следующий порядковый номер элемента e. Затем обращаемся к свойству tagName:</p>
48 <p>Самое простое - записать названия элементов. Для этого обращаемся к коллекции потомков элемента &lt;body&gt; и перебираем их, подставляя следующий порядковый номер элемента e. Затем обращаемся к свойству tagName:</p>
49 // Выбор элемента 1-го уровня let elementLevel1 = document.body.children[e]; // Запись названия элемента 1-го уровня let elementLevel1Name = elementLevel1.tagName; // Выбор названия элемента 1-го уровня console.log('НАЙДЕН ЭЛЕМЕНТ 1-ГО УРОВНЯ &lt;' + elementLevel1Name + '&gt;'); // Уведомление о найденном элементе 1-го уровня objectToStringify['element' + e + 'Level1'] = [{['element' + e + 'Level1Name']: elementLevel1Name}]; // Запись названия элемента 1-го уровня в объект<p>Здесь и далее мы конструируем понятные названия ключей в квадратных скобках с помощью комбинации текста в кавычках и названий соответствующих переменных.</p>
49 // Выбор элемента 1-го уровня let elementLevel1 = document.body.children[e]; // Запись названия элемента 1-го уровня let elementLevel1Name = elementLevel1.tagName; // Выбор названия элемента 1-го уровня console.log('НАЙДЕН ЭЛЕМЕНТ 1-ГО УРОВНЯ &lt;' + elementLevel1Name + '&gt;'); // Уведомление о найденном элементе 1-го уровня objectToStringify['element' + e + 'Level1'] = [{['element' + e + 'Level1Name']: elementLevel1Name}]; // Запись названия элемента 1-го уровня в объект<p>Здесь и далее мы конструируем понятные названия ключей в квадратных скобках с помощью комбинации текста в кавычках и названий соответствующих переменных.</p>
50 <p>С получением атрибутов ситуация усложняется: сначала нужно проверять их наличие у элемента.</p>
50 <p>С получением атрибутов ситуация усложняется: сначала нужно проверять их наличие у элемента.</p>
51 // Запись атрибутов элемента 1-го уровня // Проверка элемента 1-го уровня на наличие атрибутов if (elementLevel1.attributes.length &gt; 0) {<p>Реакция конвертера будет отличаться в зависимости от результата проверки. Если атрибуты найдены, нужно сосчитать их количество, перебрать по очереди и красиво записать в нужное место.</p>
51 // Запись атрибутов элемента 1-го уровня // Проверка элемента 1-го уровня на наличие атрибутов if (elementLevel1.attributes.length &gt; 0) {<p>Реакция конвертера будет отличаться в зависимости от результата проверки. Если атрибуты найдены, нужно сосчитать их количество, перебрать по очереди и красиво записать в нужное место.</p>
52 <p>Для перебора атрибутов у нас отдельный вложенный цикл, где переменная a является сокращением от слова "attribute".</p>
52 <p>Для перебора атрибутов у нас отдельный вложенный цикл, где переменная a является сокращением от слова "attribute".</p>
53 // Если атрибуты элемента 1-го уровня найдены let elementLevel1Attributes = elementLevel1.attributes; // Выбор атрибутов элемента 1-го уровня // Объявление массива для структурированной записи атрибутов элемента 1-го уровня let saveAttributes = new Array(); // Перебор и запись в корневой объект objectToStringify атрибутов элемента 1-го уровня for (let a = 0; a &lt; elementLevel1Attributes.length; a++) { // Уведомление о найденном атрибуте элемента 1-го уровня console.log('Атрибут элемента 1-го уровня &lt;' + elementLevel1Name + '&gt;: ' + elementLevel1Attributes[a].name + '=' + elementLevel1Attributes[a].value); let attributeName = elementLevel1Attributes[a].name; // Запись названия атрибута элемента 1-го уровня let attributeValue = elementLevel1Attributes[a].value; // Запись значения атрибута элемента 1-го уровня // Запись названия и значения текущего атрибута элемента 1-го уровня в объект let currentAttribute = { ['element' + e + 'Level1' + 'attribute' + a]: [ { ['element' + e + 'Level1' + 'attribute' + a + 'Name']: attributeName }, { ['element' + e + 'Level1' + 'attribute' + a + 'Value']: attributeValue } ] }; // Сохранение структурированного атрибута элемента 1-го уровня в массив saveAttributes.push(currentAttribute); }; // Запись структурированных атрибутов элемента 1-го уровня из массива в корневой объект objectToStringify objectToStringify['element' + e + 'Level1'][1] = { ['element' + e + 'Level1Attributes']: saveAttributes };<p>Если атрибуты не были найдены, записываем пустое значение.</p>
53 // Если атрибуты элемента 1-го уровня найдены let elementLevel1Attributes = elementLevel1.attributes; // Выбор атрибутов элемента 1-го уровня // Объявление массива для структурированной записи атрибутов элемента 1-го уровня let saveAttributes = new Array(); // Перебор и запись в корневой объект objectToStringify атрибутов элемента 1-го уровня for (let a = 0; a &lt; elementLevel1Attributes.length; a++) { // Уведомление о найденном атрибуте элемента 1-го уровня console.log('Атрибут элемента 1-го уровня &lt;' + elementLevel1Name + '&gt;: ' + elementLevel1Attributes[a].name + '=' + elementLevel1Attributes[a].value); let attributeName = elementLevel1Attributes[a].name; // Запись названия атрибута элемента 1-го уровня let attributeValue = elementLevel1Attributes[a].value; // Запись значения атрибута элемента 1-го уровня // Запись названия и значения текущего атрибута элемента 1-го уровня в объект let currentAttribute = { ['element' + e + 'Level1' + 'attribute' + a]: [ { ['element' + e + 'Level1' + 'attribute' + a + 'Name']: attributeName }, { ['element' + e + 'Level1' + 'attribute' + a + 'Value']: attributeValue } ] }; // Сохранение структурированного атрибута элемента 1-го уровня в массив saveAttributes.push(currentAttribute); }; // Запись структурированных атрибутов элемента 1-го уровня из массива в корневой объект objectToStringify objectToStringify['element' + e + 'Level1'][1] = { ['element' + e + 'Level1Attributes']: saveAttributes };<p>Если атрибуты не были найдены, записываем пустое значение.</p>
54 } else { // Если у элемента 1-го уровня нет атрибутов, вывод уведомления в консоль console.log('Элемент 1-го уровня &lt;' + elementLevel1Name + '&gt; не имеет атрибутов.'); // Если у элемента 1-го уровня нет атрибутов, то объект с местом под них оставляем с пустым значением objectToStringify['element' + e + 'Level1'][1] = { ['element' + e + 'Level1Attributes']: '' }; };<p>После атрибутов нужно записать содержимое элемента - то есть текст, вложенные элементы или пустое значение. Для этого нужно измерить количество вложенных элементов, а если их нет, то проверить наличие текста. Это делается следующим образом:</p>
54 } else { // Если у элемента 1-го уровня нет атрибутов, вывод уведомления в консоль console.log('Элемент 1-го уровня &lt;' + elementLevel1Name + '&gt; не имеет атрибутов.'); // Если у элемента 1-го уровня нет атрибутов, то объект с местом под них оставляем с пустым значением objectToStringify['element' + e + 'Level1'][1] = { ['element' + e + 'Level1Attributes']: '' }; };<p>После атрибутов нужно записать содержимое элемента - то есть текст, вложенные элементы или пустое значение. Для этого нужно измерить количество вложенных элементов, а если их нет, то проверить наличие текста. Это делается следующим образом:</p>
55 // Проверка вида содержимого элемента 1-го уровня // Проверка на наличие элементов 2-го уровня if (elementLevel1.children.length &gt; 0) { // Если элементы 2-го уровня найдены } else if (elementLevel1.children.length == 0) { // Если элементы 2-го уровня не найдены, проверка элемента 1-го уровня на наличие текста или пустого значения if (elementLevel1.textContent) { // Если есть текст } else { // Если содержимого нет }; };<p>После проверки происходит запись найденного содержимого элемента первого уровня:</p>
55 // Проверка вида содержимого элемента 1-го уровня // Проверка на наличие элементов 2-го уровня if (elementLevel1.children.length &gt; 0) { // Если элементы 2-го уровня найдены } else if (elementLevel1.children.length == 0) { // Если элементы 2-го уровня не найдены, проверка элемента 1-го уровня на наличие текста или пустого значения if (elementLevel1.textContent) { // Если есть текст } else { // Если содержимого нет }; };<p>После проверки происходит запись найденного содержимого элемента первого уровня:</p>
56 // Запись структурированного содержимого элемента 1-го уровня из массива в корневой объект objectToStringify objectToStringify['element' + e + 'Level1'][2] = { ['element' + e + 'Level1Content']: elementLevel1Content };<p>…если содержимое - это элементы второго уровня.</p>
56 // Запись структурированного содержимого элемента 1-го уровня из массива в корневой объект objectToStringify objectToStringify['element' + e + 'Level1'][2] = { ['element' + e + 'Level1Content']: elementLevel1Content };<p>…если содержимое - это элементы второго уровня.</p>
57 let elementLevel1Text = elementLevel1.textContent; // Выбор текстового контента внутри элемента 1-го уровня console.log('Элемент 1-го уровня &lt;' + elementLevel1Name + '&gt; содержит текст: "' + elementLevel1Text + '"'); // Запись текста элемента 1-го уровня в корневой объект objectToStringify objectToStringify['element' + e + 'Level1'][2] = { ['element' + e + 'Level1Content']: elementLevel1Text };<p>…если содержимое - текст.</p>
57 let elementLevel1Text = elementLevel1.textContent; // Выбор текстового контента внутри элемента 1-го уровня console.log('Элемент 1-го уровня &lt;' + elementLevel1Name + '&gt; содержит текст: "' + elementLevel1Text + '"'); // Запись текста элемента 1-го уровня в корневой объект objectToStringify objectToStringify['element' + e + 'Level1'][2] = { ['element' + e + 'Level1Content']: elementLevel1Text };<p>…если содержимое - текст.</p>
58 // Если элемент 1-го уровня не содержит ни вложенных элементов, ни даже текста console.log('Элемент 1-го уровня &lt;' + elementLevel1Name + '&gt; не содержит текста.'); // Если элемент 1-го уровня не имеет содержимого, то объект с местом под содержимое оставляем с пустым значением objectToStringify['element' + e + 'Level1'][2] = { ['element' + e + 'Level1Content']: ''<p>…если нет содержимого.</p>
58 // Если элемент 1-го уровня не содержит ни вложенных элементов, ни даже текста console.log('Элемент 1-го уровня &lt;' + elementLevel1Name + '&gt; не содержит текста.'); // Если элемент 1-го уровня не имеет содержимого, то объект с местом под содержимое оставляем с пустым значением objectToStringify['element' + e + 'Level1'][2] = { ['element' + e + 'Level1Content']: ''<p>…если нет содержимого.</p>
59 <p>Не будем душнить и бомбить вас кодом дальше: элементы второго и третьего уровней записываются аналогичным образом во время перебора содержимого их родительских элементов первого уровня - это можно увидеть ниже, в финальной версии кода.</p>
59 <p>Не будем душнить и бомбить вас кодом дальше: элементы второго и третьего уровней записываются аналогичным образом во время перебора содержимого их родительских элементов первого уровня - это можно увидеть ниже, в финальной версии кода.</p>
60 <p>Для второго и третьего уровней в их собственных циклах for элементы перебираются с помощью переменных e2 и e3 соответственно, а в переборе их атрибутов фигурируют переменные a2 и a3 - всё по аналогии с первым уровнем.</p>
60 <p>Для второго и третьего уровней в их собственных циклах for элементы перебираются с помощью переменных e2 и e3 соответственно, а в переборе их атрибутов фигурируют переменные a2 и a3 - всё по аналогии с первым уровнем.</p>
61 <p>Когда циклы перебора/записи в объект элементов всех уровней, их атрибутов и содержимого закончены, мы скармливаем получившийся JavaScript-объект встроенному методу <a>JSON.stringify()</a>для сериализации:</p>
61 <p>Когда циклы перебора/записи в объект элементов всех уровней, их атрибутов и содержимого закончены, мы скармливаем получившийся JavaScript-объект встроенному методу <a>JSON.stringify()</a>для сериализации:</p>
62 let result = JSON.stringify(objectToStringify); // Сериализуем объект<p>После этого нужно вывести результат на страницу с помощью команды на перезапись элемента &lt;body&gt; содержимым переменной result:</p>
62 let result = JSON.stringify(objectToStringify); // Сериализуем объект<p>После этого нужно вывести результат на страницу с помощью команды на перезапись элемента &lt;body&gt; содержимым переменной result:</p>
63 document.body.innerHTML = result; // Заменяем тело страницы на наш JSON<p>Итоговую версию кода можно посмотреть (и даже скопипастить, если лень разбираться) по <a>ссылке</a>. В результате его выполнения наша страница превращается в JSON-строку и принимает следующий вид:</p>
63 document.body.innerHTML = result; // Заменяем тело страницы на наш JSON<p>Итоговую версию кода можно посмотреть (и даже скопипастить, если лень разбираться) по <a>ссылке</a>. В результате его выполнения наша страница превращается в JSON-строку и принимает следующий вид:</p>
64 {"element0Level1":[{"element0Level1Name":"P"},{"element0Level1Attributes":[{"element0Level1attribute0":[{"element0Level1attribute0Name":"class"},{"element0Level1attribute0Value":"myclass"}]},{"element0Level1attribute1":[{"element0Level1attribute1Name":"style"},{"element0Level1attribute1Value":"margin: 1px;"}]}]},{"element0Level1Content":"Какой-то абзац."}],"element1Level1":[{"element1Level1Name":"DIV"},{"element1Level1Attributes":""},{"element1Level1Content":[{"element0Level2":[{"element0Level2Name":"P"},{"element0Level2Attributes":""},{"element0Level2Content":[{"element0Level3":[{"element0Level3Name":"SPAN"},{"element0Level3Attributes":""},{"element0Level3Content":"Другой абзац (элемент 3-го уровня)"}]}]}]},{"element1Level2":[{"element1Level2Name":"SPAN"},{"element1Level2Attributes":""},{"element1Level2Content":"Другой абзац (элемент 2-го уровня)"}]},{"element2Level2":[{"element2Level2Name":"SPAN"},{"element2Level2Attributes":""},{"element2Level2Content":[{"element0Level3":[{"element0Level3Name":"A"},{"element0Level3Attributes":[{"element0Level3attribute0":[{"element0Level3attribute0Name":"href"},{"element0Level3attribute0Value":"#"}]}]},{"element0Level3Content":"Какая-то ссылка (элемент 3-го уровня)."}]}]}]},{"element3Level2":[{"element3Level2Name":"IMG"},{"element3Level2Attributes":[{"element3Level2attribute0":[{"element3Level2attribute0Name":"src"},{"element3Level2attribute0Value":"images/test.png"}]},{"element3Level2attribute1":[{"element3Level2attribute1Name":"alt"},{"element3Level2attribute1Value":"Тестовое изображение"}]}]},{"element3Level2Content":""}]}]}],"element2Level1":[{"element2Level1Name":"SCRIPT"},{"element2Level1Attributes":[{"element2Level1attribute0":[{"element2Level1attribute0Name":"src"},{"element2Level1attribute0Value":"script.js"}]}]},{"element2Level1Content":""}]}<p>В любом JSON-форматтере можно просмотреть результат в более читабельном виде.</p>
64 {"element0Level1":[{"element0Level1Name":"P"},{"element0Level1Attributes":[{"element0Level1attribute0":[{"element0Level1attribute0Name":"class"},{"element0Level1attribute0Value":"myclass"}]},{"element0Level1attribute1":[{"element0Level1attribute1Name":"style"},{"element0Level1attribute1Value":"margin: 1px;"}]}]},{"element0Level1Content":"Какой-то абзац."}],"element1Level1":[{"element1Level1Name":"DIV"},{"element1Level1Attributes":""},{"element1Level1Content":[{"element0Level2":[{"element0Level2Name":"P"},{"element0Level2Attributes":""},{"element0Level2Content":[{"element0Level3":[{"element0Level3Name":"SPAN"},{"element0Level3Attributes":""},{"element0Level3Content":"Другой абзац (элемент 3-го уровня)"}]}]}]},{"element1Level2":[{"element1Level2Name":"SPAN"},{"element1Level2Attributes":""},{"element1Level2Content":"Другой абзац (элемент 2-го уровня)"}]},{"element2Level2":[{"element2Level2Name":"SPAN"},{"element2Level2Attributes":""},{"element2Level2Content":[{"element0Level3":[{"element0Level3Name":"A"},{"element0Level3Attributes":[{"element0Level3attribute0":[{"element0Level3attribute0Name":"href"},{"element0Level3attribute0Value":"#"}]}]},{"element0Level3Content":"Какая-то ссылка (элемент 3-го уровня)."}]}]}]},{"element3Level2":[{"element3Level2Name":"IMG"},{"element3Level2Attributes":[{"element3Level2attribute0":[{"element3Level2attribute0Name":"src"},{"element3Level2attribute0Value":"images/test.png"}]},{"element3Level2attribute1":[{"element3Level2attribute1Name":"alt"},{"element3Level2attribute1Value":"Тестовое изображение"}]}]},{"element3Level2Content":""}]}]}],"element2Level1":[{"element2Level1Name":"SCRIPT"},{"element2Level1Attributes":[{"element2Level1attribute0":[{"element2Level1attribute0Name":"src"},{"element2Level1attribute0Value":"script.js"}]}]},{"element2Level1Content":""}]}<p>В любом JSON-форматтере можно просмотреть результат в более читабельном виде.</p>
65 Результат конвертации HTML в JSON: вид в JSON-форматтере<em>Скриншот: Skillbox Media</em><p>На всякий случай прогоним результат и через валидатор JSON.</p>
65 Результат конвертации HTML в JSON: вид в JSON-форматтере<em>Скриншот: Skillbox Media</em><p>На всякий случай прогоним результат и через валидатор JSON.</p>
66 Результат конвертации HTML в JSON: вид в валидаторе JSON<em>Скриншот: Skillbox Media</em><p>А в консоли - вот такая красота.</p>
66 Результат конвертации HTML в JSON: вид в валидаторе JSON<em>Скриншот: Skillbox Media</em><p>А в консоли - вот такая красота.</p>
67 Результат конвертации HTML в JSON: вид уведомлений в консоли<em>Скриншот: Skillbox Media</em><p>Мы рассмотрели один из способов превращения HTML-файла в JSON-строку. Вариантов реализации может быть много, поэтому вид кода будет сильно зависеть от ваших задач. Руководствуясь указанным алгоритмом и встроенными методами языка JavaScript, вы сможете самостоятельно реализовать подобный конвертер. А о том, как выполнить обратную конвертацию, мы расскажем в следующей статье.</p>
67 Результат конвертации HTML в JSON: вид уведомлений в консоли<em>Скриншот: Skillbox Media</em><p>Мы рассмотрели один из способов превращения HTML-файла в JSON-строку. Вариантов реализации может быть много, поэтому вид кода будет сильно зависеть от ваших задач. Руководствуясь указанным алгоритмом и встроенными методами языка JavaScript, вы сможете самостоятельно реализовать подобный конвертер. А о том, как выполнить обратную конвертацию, мы расскажем в следующей статье.</p>