JSON, який можна коментувати

Не всі JSON не можна коментувати (наприклад, Хром[иум] цілком переносить коментарі в manifest.json), але в стандарті не передбачені коментарі до нього. Тому ряд функцій в NodeJS не обробляють коментарі у форматі JS і вважають їх помилкою. Точно так само, AJAX формату JSON приймає їх за помилку. Тому для конфігураційних файлів у форматі JSON є маса незручностей при спробах їх використовувати як людино-файли читаються. Може бути, це іноді добре. Якщо хочемо прокоментувати, то будемо змушені оформити коментар під або над рядком як «ключ-значення».
...{...
"some-key_comment":"my comment for key and value",
"some-key":"some-value",
...}...
Але якщо коментарі не пишемо, слідуючи суворості протоколів, помилки виникають вже з-за іншого фактора забування сенсу настройок при редагуванні людиною.
...{...
"some-key":"some-value", //будь-який key?? Ай, коментарі - не можна!
...}...

Придумаємо JSON-подібний формат з коментарями в стилі JS, щоб їх можна було виконувати як JS, а, очистивши від коментарів — читати як JSON. ("TL:DR: покажіть мені код.")

Сир-бор і джерело
До речі, Дуглас Крокфорд, що це все влаштував, у 2012 році пояснив: )

Я прибрав коментарі з JSON, тому що бачив людей, які використовують їх для зберігання директив розбору — практика, яка зруйнувала б сумісність (формату). Я знаю, що відсутність коментарів деяких засмучує, але їх (коментарів) не повинно бути.

Припустимо, ви використовуєте JSON для зберігання конфігураційних файлів, які звикли коментувати. Вставте будь-які коментарі, як вам подобається. Потім пропустіть їх через JSMin перед роботою JSON-парсера.
Зробив він це на G+, де можна ставити тільки «плюси», а коментарі закрив. Так що, якою б не була реакція суспільства під поясненням, ми побачимо тільки «плюси» (або дивитися у тих, хто расшаривал цей пост).

І цитата Крокфорда з іншого місця:
Основна причина, чому я видалив коментарі — були люди, які намагалися парсити дані на основі коментарів, що повністю ламало сумісність. Я ніяк не міг контролювати їх, тому кращим виходом було коментарі видалити.


Тому далі читаємо, клікнувши і погодившись на обіцянку:
«Обіцяю, що я буду обережний і не буду використовувати коментарі для парсингу даних!
Все вже зроблено до нас
В тому і справа, що потрібно ще один парсер, а так — великої проблеми немає. І проблема цим не обмежується — іноді треба файл злегка змінити, залишивши коментарі. Першу частину (парсер) вирішили, наприклад, через JSON.minify(). Другу і ряд інших проблем (кінцеві коми або взагалі без них, багаторядкові коменти, ключі і рядка-значення без лапок) — не полінувалися вирішити в Hjson, витративши 750 рядків на код JS (з коментарями на 10-15%).

Стоп, а чи потрібно це взагалі?
Безсумнівно, суворим програмістам (таким, які пишуть коментарі значення ключів в JSON), а також роботам (мережевим і взагалі) це не потрібно. Вони чудово перекодируют імена ключів в будь-якому знайомому їм конфіги, а програмісти — так взагалі, мають ще інтелект, що дозволяє їм розбиратися в незнайомих назвах і будувати евристики за їх розшифровці без жодного комп'ютера. Решта, в тому числі не суворі програмісти, вважають коментарі корисними і витрачають час не тільки на їх читання іноді, але і на їх написання. Безсумнівно, Крокфорд відноситься до суворих програмістам, а творці YAML — ні. З цим доводиться миритися і з'єднувати світи роботів (і с. п.) і людей.

Є ще хакери, яким підійде абсолютно хакерський, дійсний спосіб запису JSON з послідовним повторенням однакових ключів (JS+»use strict" дасть помилку). Значення першого ключа в більшості парсерів не збережеться, тому його (і всі такі, крім останнього) можна використовувати як коментарі. Спосіб теж страждає «машинностью».

...{...
"some-key":"comments_comments",
"some-key":"some-value",
...}...

Отже, не всі будуть за «ще один формат, 16-й за рахунком». Будь-яка спроба побудувати, а тим більше, застосувати конвертор форматів призведе до ігнорування деякою частиною девелоперських юнітів даного формату. У тих же індивідуумах, в яких дивним чином поєднуються осколки різних світів, які ще не визначилися зі своєю сутністю, процедури конвертації пвиявляться корисними. Принаймні, на перших порах, по мірі перетворення.

Тому даний формат містить в собі непоєднуване, подібно до комп'ютера для блондинки: з одного боку, методи перетворень, які під силу застосувати тільки роботам, з іншого боку, результати постають у більш человекочитаемой формі.

Міст між роботами і людьми
Можна придумати плагін до Grunt/Gulp (наприклад, grunt-strip-json-comments, Gulp...) для очищення файлів від комментриев. Але суть дії зводиться до невеликого (до 1 К) регулярного виразу, що простіше написати в Gruntfile.js ніж у нього ж вписувати ще один плагін. Більше того, таке ж вираження потрібно і для JS на клієнта, щоб читати той же JSON, тому від його явного виду ми все одно не втечемо.

Методи для перетворення форматів зібрані в об'єкт jsonComm, який працює в середовищі Javascript. Для рішення приватних задач не потрібен весь об'єкт — не завжди має сенс брати в проект всі методи. Наприклад із завданням простого видалення коментарів (як у gulp-strip-json-comments) справляється метод, що складається з одного регулярного виразу (jsonComm.unComment(), до 1 КБ нестисненого коду; приклад далі; в тестовому розділі проекту jsonComm є тести і бенчмарки для оцінки коректності та швидкодії), яке навіть не треба компілювати, якщо немає мети застосовувати різні налаштування правил.

Налаштування можуть бути, наприклад, такі. Яким символом відзначати початок коментаря? Якщо в середовищі чистого JS є впевнену відповідь — "//", то прихильники Пайтона або YAML скажуть — "#". Спроби об'єднати непримиренних призводять до налаштувань правил і до конверторів — тим самим, з яких, в тому числі, почали. У середовищі адептів JS немає потреби в налаштуваннях, і вони випалять з проекту згадка про "#". Тому що не можна витрачати 36 микросекуд (мікро-) на генерацію регекспа заради лояльності до такої єресі. Лоялісти — теж випалять, але подовжать регексп і стануть витрачати 0.1-0.5 (умовно) мікросекунд (мікро-) вже не на генерацію, а на кожен цикл перекодування. За це їх ненавидять пуритани. Адже роботи мислять набагато швидше, і їм повільність бачиться в іншому масштабі.

Які завдання можна вирішувати при коментуванні JSON?
  • просто читати в JS або NodeJS формат jsonComm (з коментарями), видаляти з них коментарі і далі верифікувати як звичайний JSON в JSON.parse(); те ж саме, що робить більшість проектів за додавання коментарів в JSON. Працює швидко (десятки-сотні мкс).
  • читати не JSON, а файли JS (з кодом) щоб з решти взяти деякі константи параметри (наприклад, в NodeJS), коли файл JS буде їх теж використовувати при своєму виконанні в іншому місці (клієнт) — своєрідний шаблон з спрощенням структури конфігурації;
  • як у попередньому пункті, але вже хочеться змінити деякі настройки після прочитання (наприклад, в Ноді оновити номер складання або внести налаштування конфига), щоб далі JS на клієнті, нічого не підозрюючи, використав їх. Це — аналог шаблону на читання-запис.
Тут — не всі мислимі завдання, але група, достатня для простого конфігурування проекту. Замість Yaml з коментарями або костыльных коментарів в чистому JSON — пишемо jsonComm з розширенням *.js, який може читатися як JSON (на сервері, при складанні проекту або на клієнті), або виконуватися як JS, маючи коментарі в JS — або YAML-стилі.

Завдання поділяються на 2 практичних випадку — коли нам не потрібно відредагувати свій jsonComm, і коли редагувати потрібно, при цьому залишаючи всі коментарі. Коли відбувається тільки читання (це ж — випадок клієнтського AJAX), обмежуємося єдиним методом jsonComm.unComment() c одним регекспом, і далі — JSON.parse().

Випадок запису змінених значень або ключів вимагатиме невеликий процедури парсинга текстового файлу JsonComm (з коментарями, без їх вилучення) або JS, щоб точково змінити потрібне. Маніпуляція можлива для файлів ".*.js", якщо коди мови в них не будемо чіпати скриптами — потрібно лише не помилятися в запису значень ключів. До необхідних методів додається другий: jsonComm.change().

Які завдання можна вирішувати при коментуванні JSON?
Завдання академічного типу:
  • отримати «валідний» доступ до коментарів jsonComm, перевівши їх спочатку в пари «ключ#»-«коментар», вибравши основу ключа з тієї рядки, біля якої він знайдений, а потім, після парсинга з правильного JSON — обробляти їх далі (наприклад, переводячи в інший формат);
  • працювати з Yaml безпосередньо (але втрачаємо визнану браузером/середовищем JS основу для валідації)
  • взаємне перетворення в Yaml і назад через вище зроблений валідний JSON;
  • для XML; тоді вийде кластер з четвірки мов опису даних, 2 з яких визнані в браузерах і численних обчислювальних середовищах.
Особливість цих завдань — практичної необхідності в них немає, але бачачи нішу, місце під них зарезервовано (функції toYaml, toXml, fromYaml, fromXml, to; остання — це «jsonComm»). Без коментарів — такий кластер і без того вже є в роботах інших бібліотек. Аби влитися в нього з коментарями, треба почати хоча б з функції перекладу коментарів jsonComm в один з валідних і визнаних форматів. Очевидно, перший кандидат — JSON.

Перше ж знайомство зі способами коментування створює багато запитань — до яких ключів привязвать коментарі до знайденої пари, а яким — після? Наприклад, коментарі після роздільника-коми, але стоять на тій же рядку, зазвичай відносяться до попередньої парі, тому на роздільник буде впливати і закінчення рядка. Друге: багаторядкові коментарі логічно можуть ставитися до різних суміжних парам. Третє: а до чого відносяться коментарі в масивах? Їхні ключі неявно виражені, і логічно було б створити поруч лежить масив. А якщо він багатовимірний і з рідким заповненням? Четверте: коментарів на рядку може бути кілька; пара може бути розтягнута на 3 і більше рядків.

Весь цей круг не менш надуманих, але реальних проблем потребує досить продуманого підходу, щоб автоматична конвертація коментарів не призводила до погіршення доступності форматів. Тому не будемо поспішати з їх виготовленням. Займемося краще формальним описом граматики jsonComm.

Граматика jsonComm
Найчастіше зустрічаються пари в файлах JSON, зписанные на окремих рядках:
<набір пробільних відступів>"<ключ>": <значення>

Значення — рядок в лапках або інші терми за всіма правилами JSON. Ключ — будь-який рядок, лише з особливим екрануванням лапок всередині себе. Між елементами можуть бути пробільні символи, а розділяються пари комами або дужками, які можуть стояти де завгодно до або після пар, в тому числі, на сусідніх рядках.

У нас буде дуже схожий формат (jsonComm), з тією різницею, що на місці пробільних символів можуть бути коментарі 2 типів.

Виявляється, економічніше при цьому орієнтуватися не по рядках, а за роздільниками (дужкам, ком). Переноси рядків для багаторядкових коментарів взагалі не мають значення, а для однорядкових служать ознакою кінця. Це вплине на те, якою парсер буде працювати в алгоритмі перетворення.

Далі, при вирішенні творчого завдання з питання того, до якої парі віднести коментарі, розташування роздільника і переносів рядків знову буде мати значення. Для видалення коментарів — виявляється, що переноси рядків не важливі (не слід видаляти лише кінцевий перенесення однорядкового коментаря).

З урахуванням сказаного, основна конструкція граматики jsonComm виглядає так:
(("{" | "[" | ",")<прогалини>)
<прогалини-коменти>
(<прогалини>"<ключ>"<прогалини>)
<прогалини-коменти>
(<прогалини>(":")<прогалини>)
<прогалини-коменти>
(<прогалини><значення><прогалини>)
<прогалини-коменти>
|
<прогалини-коменти>
(<прогалини><значення><прогалини>)
<прогалини-коменти>
(<прогалини>("}" | "]" | ","))

Після фільтрації викидається все, що не в дужках, і залишається все, що зображено в круглих дужках. З деякими особливостями, звичайно, що на цій спрощеній схемі не відображені (порожнє значення означає значення-структуру). Схема може пропустити неправильний JSON, може взагалі пропустити будь-який текст, крім коментарів, наприклад, програму чи текст книги. І це добре тим, що при валідації, якщо її роблять, JSON все одно перевіряється, а якщо валідації немає, а текст парс JS-компілятором, то потреба у видаленні коментарів відсутня, схема в цьому режимі не працює.

Схожа, більш складна схема потрібна для вставляння коментарів-значень (функція jsonComm.comm2json()). У ній jsonComm виду
...
,"some-key":"some-value" //comments_comments
...}...

створюємо
...
"some-key#":"comments_comments",
"some-key":"some-value",
...}...

або без строчки з ключем для коментаря. Якщо в області тексту, що відноситься до парі, зустрілося кілька коментарів, всіх їх копіюють значення «some-key#». Але якщо коментар не зустрівся в районі пари (в масиві, до або після всіх дужок), він ігнорується. Всі символи коментаря доводиться перетворювати в валідні для JSON. Наприклад, таби — в "\t", "\" — "\\",…

Як на практиці містити JsonComm?
Досі ми могли записати без проблем і плагінів тільки JSON з усіма застереженнями відсутність коментарів або з присутністю, але у вигляді значень (або правити JS як текстові файли, або зберігати в БД). Зараз будемо користуватися змінними (для NodeJS) файлами jsonComm, що мають розширення *.js.

Виявлено 2 практичні ніші застосування JsonComm-файлів: на читання конфігурацій, оформлених з коментарями, на оновлення конфігурацій, і одна академічна — конвертор форматів.

Якщо файли треба тільки читати (клієнтський JS та інше), читаємо їх як xhr.responseText в AJAX або як *.js і перетворимо JsonComm в об'єкти-структури з валідацією через JSON.parse().

Якщо файли потрібно модифікувати, то для швидкості роботи використовуємо алгоритм пошуку і заміни з унікальним джерелам, не повторюються у файлі (jsonComm.change()). Тоді не потрібно робити дерево розбору, одночасно залишаючи коментарі (втім, це теж не повинно бути повільно, але окремий складний однопрохідний алгоритм).

Немає проблем додати пайтоновский стиль однорядкових коментарів (#comments_comments). Але тоді не буде працювати спосіб читання файлу *.js. У коді проекту закладена можливість відключити синтаксис "#" у коментарів (на початковому етапі компіляції регекспа).

Прості випадки, коли це потрібно:

* У збирача проекту на Grunt/Gulp/… обчислюємо новий номер версії і запам'ятовуємо його в той же файл конфігураци.

* там же, в збирача, створюємо константи проекту на основі інших параметрів складання і пишемо їх як параметри для JS.

Трохи більш складно, клієнтський JS теж може придбати функцію запису таких файлів, через відправку результату на сервер. Це дасть ще більше варіантів використання (складальна панель на клієнті), залишаючи коментарі у файл. Для цього йому треба модифікувати і відправити рядок (образ багаторядкового файлу на сервер, а там її записати у файл (звичайно, з вирішенням питань безпеки).

Реалізація
Щоб довго не крутити цикли, перетворення виконується «одним махом» на регулярних виразах.

Выкусывание коментарів

Перетворювач фактично працює як цикл по рядках, методично выкусывая коментарі і пропускаючи допустимі фрагменти JSON. На його базі нескладно побудувати і распознаватели тексту коментарів, щоб їх зберігати в особливі ключі-значення. Таким способом, ми допускаємо коментарі для подальших операцій, але не для того, щоб «порушити сумісність» (при бажанні завжди можна), а щоб код з коментарем був більш зручною записом гірше читається вирази з 2 пар «ключ-коментар» і «ключ-значення».

Не
"ключ_": "коментар",
"ключ": "значення",


"ключ": "значення" //коментар


Рішення виконує також завдання по розподілу відповідальності за валідність коду. Все, що відноситься до коментарів, контролюється візуально і з підсвічуванням синтаксису в IDE розробником. Правильність решти JSON розбирає стандартний парсер JSON.parse().

Почнемо з простого. Як працює приблизно парсинг на регекспах? Спробуємо видаляти кінцеві коментарі. (Код не використовується далі, він — тільки для прикладу.)

('\n'+строки_файла).replace(/(^|\r?\n)(([^"\r\n:]*"(\\"|[^"\r\n])*"|[^"\r\n:]*):?([^"\r\n]*"[^"\r\n]*"|[^"\r\n]*)[^\/"\r\n]*?|[^\/"\r\n]*?)(\/\*\*\/|\/\*([\s\S]?(?!\*\/))+.{3}|\/\/[^\r\n]*)/g,'$1$2')


Для розуміння, як воно влаштоване, звернемо увагу на функціональні частини:

(^|\r?\n)
— захоплюючі дужки для відображення попереднього переносу рядка.
Наступна за ним дужка і її пара — ...
[^\/"\r\n]*?)
— другі використовуються для копіювання захоплюючі дужки.
"(\\"|[^"\r\n])*"
— ключ або рядок в лапках; якщо дужки немає — далі шукається альтернатива просто

\s*\/\*\*\/|\s*\/\*([\s\S]?(?!\*\/))+.{3}
— парсер багаторядкового коментаря.
\/\/[^\r\n]*
— парсер однорядкового коментаря до кінця рядка.

З выкусыванием коментарів в кінці рядка у цього нескладного виразу — все відмінно. Гірше справа — з выкусыванием коментарів із зірочкою між ключами і значеннями. Можна знехтувати і не писати таких коментарів. Тим більше, що у «конкурента» YAML є тільки кінцеві. Але, маючи функціональні частини, вже можна побудувати більш складне вираз, щоб не накладати таких обмежень. При цьому доведеться не просто залишати «все до коментаря в рядку», але і між ними ускладнюються залишаються фрагменти. Фактично, це — вся jsonComm.unComment(jsonCommString). Саме цей рядок можна копіювати в Gruntfile.js замість підключення модуля, щоб очистити рядок JSON від коментарів.

jsonCommString.replace(/(?:(?:((?:\{|,)\s*)(?:(?:\s*(?:\/\/|#)[^\r\n]*(\r?\n|$))*(?:\s*\/\*\*\/|\s*\/\*(?:[\s\S]?(?!\*\/))+.{3})*)*(\s*"(?:\\"|[^\r\n"])*"\s*)(?:(?:\s*(?:\/\/|#)[^\r\n]*(\r?\n|$))*(?:\s*\/\*\*\/|\s*\/\*(?:[\s\S]?(?!\*\/))+.{3})*)*(\s*:\s*)(?:(?:\s*(?:\/\/|#)[^\r\n]*(\r?\n|$))*(?:\s*\/\*\*\/|\s*\/\*(?:[\s\S]?(?!\*\/))+.{3})*)*(\s*(?:[0-9.eE+-]+|true|false|null|"(?:\\"|[^\r\n"])*"|(?!:\{|:\[))\s*)(?:(?:\s*(?:\/\/|#)[^\r\n]*(\r?\n|$))*(?:\s*\/\*\*\/|\s*\/\*(?:[\s\S]?(?!\*\/))+.{3})*)*(\s*(?:\}|(?!,))\s*)?)+?|(?:((?:\[|,)\s*)(?:(?:\s*(?:\/\/|#)[^\r\n]*(\r?\n|$))*(?:\s*\/\*\*\/|\s*\/\*(?:[\s\S]?(?!\*\/))+.{3})*)*(\s*(?:[0-9.eE+-]+|true|false|null|"(?:\\"|[^\r\n"])*"|(?!:\{|:\[))\s*)(?:(?:\s*(?:\/\/|#)[^\r\n]*(\r?\n|$))*(?:\s*\/\*\*\/|\s*\/\*(?:[\s\S]?(?!\*\/))+.{3})*)*(\s*(?:\]|(?!,))\s*)?)+?|(?:(?:\s*(?:\/\/|#)[^\r\n]*(\r?\n|$))*(?:\s*\/\*\*\/|\s*\/\*(?:[\s\S]?(?!\*\/))+.{3})*)*\s*)/g,'$1$2$3$4$5$6$7$8$9$10$11$12$13$14')


Тут широко використовуються незахватывающие дужки, щоб залишити тільки захоплюючі, для подальшої простоти другого аргументу .replace(). (Підказка-лайфхак: такі рядки найкраще читати в редакторі, має виділення з підсвічуванням.)

Для перетворення рядка jsonComm в JSON достатньо цього виразу. Як показують бенчмарки, це перетворення досить добре літає — час виконання — десятки-сотні мікросекунд на сторінку (сильно залежить від складності розбору). Гірше буде справа з академічним скриптом для виведення коментарів в JSON, коли в replace() знадобиться функція.

Так, ми отримали валідний JSON, вирішивши першу частину завдання — прочитати jsonComm.

Потім, парсинг валідності залишився коду, як задумано, покладається на стандартну JSON.parse(), після чого отримуємо структуру даних в JS. Наступна частина завдання — дещо автоматично підредагувати в вихідному тексті, залишивши коментарі на місцях.

Вставка деяких оновлених значень

Створене відділення даних від коментарів прекрасно використовується для пошуку по тексту, не включає коментарі. Відповідно, редагування значень теж ведеться за шаблоном пар «ключ-значення» і не потрапляє в області коментарів, хоч би схожим на них текст там не був.

Нагадаємо обмеження, які накладаємо на правки.
  • у тексті jsonComm шукаються унікальні ключі (в лапках). Копії ключів в коментарях ігноруються. Для однакових імен ключів з різних гілок структури — зміниться перше і створиться некритична помилка в звіті.
  • ланцюжка ключів не аналізуються (для простоти і швидкості пошуку)
  • правити пари, записані не з початку рядка — без проблем, тому що розпізнавач орієнтований на дужки і коми як маркери пар. Але для зручності читання і контролю краще записувати змінні пари з початку рядка.
  • видалити пару не можна; найбільше — замінити на значення null або "". Як наслідок, редаговані ключі продовжують працювати при будь-яких автоматичних зміни, які можуть зникнути лише при ручних.
  • змінюються тільки примітиви; масиви і структури залишаються на місці. Спроба змінити структуру призводить до нефатальной помилку (пишеться в лог помилок).
  • зміна (перейменування) ключів можливо, хоча суперечить людино-орієнтованого підходу та може призвести до порушення ланцюжка автоматичних змін, яке буде складно налагоджувати. Цим механізмом, можливо, зручно змінювати значення місцями (перестановкою значень, а ключів).


Така схема не скасовує правок серіалізовать структур, але цей шлях — вже не для людей. В теперішньому вигляді правки розраховані на зміну даних без зміни структур, описаних у файлах jsonComm.

Тоді все дуже просто і швидко працює: у вихідному файлі відшукуються єдині зразки виду «ключ» (в подвійних лапках), після чого скриптом маємо доступ до значення — рядку, числа або логічного.

Зміна значень виконується функцією jsonComm.change(h), де h — спеціальний набір пар «ключ»-«нове значення». (В крайньому випадку — «ключ»- {«новий ключ»:«нове значення»}.)

Що цікаво, для .change() файл (рядок) не зобов'язаний бути приведеними до JSON і до нього не обов'язково намагатися застосовувати .unComment(). Це може бути JS-файл, який спочатку виконається (наприклад, тільки для того, щоб прочитати з нього поточні значення параметрів замість читання JSON), а потім до нього застосувати модифікація значень. Т. е. .change() — це теж досить автономна функція в збірці.

Академічні завдання: зміна формату файлу
Щоб ще більше витратити місця на бібліотеку, придумуються завдання глобальної конвертації.

● отримати коментарі в JSON (функція перетворення — jsonComm.comm2json),
● робота з YAML,
● двосторонні перетворення «jsonComm — YAML».
● то ж для «jsonComm — XML».

В силу їх незатребуваності, для останніх поставлені функції-заглушки, і тільки перша (comm2json) зроблена заради академічного інтересу, для відповіді на запитання — наскільки повільніше це буде. Доводиться робити replace, в якому захопити параметри коментарів через функцію, а потім символ за символом перевіряти коментарі і перетворювати наявні в допустимі для JSON рядкові символи.

Коротка відповідь — стає повільніше в 30 разів і теж сильно залежить від складності розбору, кількості коментарів. Тестовий приклад вклався приблизно на 1 мілісекунду, але реальність легко зробить життя складніше. Зате ми отримуємо перший інструмент для «повністю валідного» подальшого перетворення в інші формати даних (Yaml, XML).

Результати тесту
Подивимося, як на субноуте середньої руки ці 3 функції справляються з невеликим контрольним jsonComm, мають різноманітні (звичайно, не всі) складності для парсингу. На скріншотах — вихідні дані, але у проекті можна знайти код цих даних і провести тести на своєму комп'ютері і браузері. На Firefox 34 (jsonComm.unComment):

На Хромі в цьому тесті — вдвічі кращі результати.

Як виконується парсинг коментарів (jsonComm.comm2json)? Тут заміна працює через replace(,function).

У Хрому тут і далі — зіставні результати. Це означає, що його спеціально оптимізували на заміни рядків.replace()) без функцій. У будь-якому випадку, перший тест — дуже швидко, цей — помірно.

Рядки форматуються нерівно, але в даному випадку це не має великого значення, тому що призначення функції — отримати валідний JSON з валідними коментарями. Показати красиво можна і стандартними засобами, як показано далі в тесті (скріншот не наведено).

Як змінюються значення ключів (jsonComm.change)? Тут форма і красивість результату — вже на першому місці, тому що призначене для читання конфіги людьми. Правила заміни показані в об'єкті jCommChanges.

Тут можна звернути увагу, що масиви і структури не змінюються за визначенням наших правил. Навіть якщо написано «multiline1: {newKey:'newValue'}», змінюється тільки ключ, а запит на зміну значення ігнорується.

Чим більше змін потрібно зробити на тому ж ділянці jsonComm, тим повільніше працює скрипт (що логічно). Виходячи з приведених обсягів, можна оцінити, якою буде швидкість на великих JSON. Загалом, швидкість — досить хороша, якщо навіть для правок йдеться про одиницях мілісекунд.

Як згадувалося, перша функція з компилированным регекспом в стислому вигляді займає менше 1 КБ. Минифицированные перші 3 функції з викиданням нереалізованих інших заглушок — 2.1 КБ (src/jsonComm.min.js).

Нові вклади в проект
Що хотілося б побачити в проекті від нових контриб'юторів?

1) Крім академічних розділів, є елементи парсинга, які не завадило б відточувати в коді, щоб виділяти коментарі точніше (як показує тестовий висновок jsonCommTest.htm під заголовком «jsonWithComm», вихідна рядок .comm2json() не дуже досконала). Втім, в JSON.stringify вже є способи вивести рядок красивіше, як показує наступна рядок лода під заголовком «jsObjWithComm».

2) Цікаво було б порівняння швидкості зі скриптовою парсингом.

3) Не відзначаються помилки неунікального парсингу. Не обробляються JSON у вигляді одного примітиву.

4) Плагіни для Grunt, Gulp,…

Вітається тестування для складних випадків вихідних файлів і повідомлення про помилки в issues, розповсюдження посилань для іншої потенційної аудиторії (Китай і деякі інші розвинуті країни, в яких Гитхаб не заблокований).

● Все, що описано працює тут: jsonComm — проект (Github), опис проекту (англ.).
Json — стандарт, rfc-4627 про нього.
● Питання "Як мені прокоментувати JSON?" на SO.
JSON.minify() (блог) і Github/
grunt-, gulp, broccoli-, strip-json-comments (Github)
JSON Comments (інший автор)
Пропозиції щодо вдосконалення JSON (англ., 2011)
JSON5 (перегукується з попередньою)
Hjson, the Human JSON (Hjson keep my comments when updating a config file.)
[Для розробників] чи Було у вас бажання використовувати в розробках звичайні коментарі в JsON?

/>
/>


<input type=«radio» id=«vv64483»
class=«radio js-field-data»
name=«variant[]»
value=«64483» />
Так (і залишалося бажанням)
<input type=«radio» id=«vv64485»
class=«radio js-field-data»
name=«variant[]»
value=«64485» />
Ні, JsON не коментував
<input type=«radio» id=«vv64487»
class=«radio js-field-data»
name=«variant[]»
value=«64487» />
Так, і використовував, очищаючи потім JsON
<input type=«radio» id=«vv64489»
class=«radio js-field-data»
name=«variant[]»
value=«64489» />
Так, испольльзовал, парся потім його як JS
<input type=«radio» id=«vv64491»
class=«radio js-field-data»
name=«variant[]»
value=«64491» />
Коментував, але він після цього не працював: ) (йшов, наприклад, статтю)

Проголосувало 10 осіб. Утрималося-3 людини.


Прочитав я статтю? Яка частина статті мені виявилася корисною?

/>
/>

<input type=«checkbox» id=«vv64493»
class=«checkbox js-field-data»
name=«variant[]»
value=«64493» />
Не читав і не буду, з будь-якої причини
<input type=«checkbox» id=«vv64495»
class=«checkbox js-field-data»
name=«variant[]»
value=«64495» />
Тільки до ката
<input type=«checkbox» id=«vv64497»
class=«checkbox js-field-data»
name=«variant[]»
value=«64497» />
До ката, потім-код на Гітхабі, але все марно, тлін і суєта
<input type=«checkbox» id=«vv64499»
class=«checkbox js-field-data»
name=«variant[]»
value=«64499» />
Тільки до формул
<input type=«checkbox» id=«vv64501»
class=«checkbox js-field-data»
name=«variant[]»
value=«64501» />
Код на Гітхабі нагоді
<input type=«checkbox» id=«vv64503»
class=«checkbox js-field-data»
name=«variant[]»
value=«64503» />
Воду пропустив, але розбір коду виявився корисним

Проголосувало 5 осіб. Утрималося 5 чоловік.


Тільки зареєстровані користувачі можуть брати участь в опитуванні. Увійдіть, будь ласка.


Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.