Чи можете ви використовувати кінцеву кому в об'єкті JSON?


392

Коли вручну генерується об'єкт або масив JSON, часто простіше залишити коду на останньому елементі в об'єкті або масиві. Наприклад, код, який виводиться з масиву рядків, може виглядати так (у псевдокоді на C ++):

s.append("[");
for (i = 0; i < 5; ++i) {
    s.appendF("\"%d\",", i);
}
s.append("]");

даючи вам такий рядок

[0,1,2,3,4,5,]

Це дозволено?


66
Мені потрібно було шукати в Інтернеті кілька днів тому. Я не бачив відповіді тут на SO, тому, виконуючи місію сайту, я поставив це питання і відповів на нього, щоб інші могли його знайти. Це те, що Джефф прямо сказав, що хоче зробити це тут.
Бен Комбі

5
Як сказав Джефф, я вважаю, що цілком чудово використовувати SO як "зошит" речей, на які вам довелося витратити деякий час, шукаючи. Звичайно, це просто в кінці цих типів елементів, але я все-таки вважаю за доцільне, тим більше, що різні механізми javascript вирішуватимуть це по-різному.
pkaeding

6
Мені теж це було цікаво, тому це цілком розумне питання.
ходжу

48
Для всіх тих кусачів, які хтось задав просте запитання, будь ласка, відступайте. Це було одним із перших звернень у Google, і це допомогло мені швидко відповісти на відповідь. Дякую ОП.

40
Цікаво (або жахливо) в IE 8 щойно я виявив, що alert([1, 2, 3, ].length)відображатиметься "4".
Даніель Ервікер

Відповіді:


250

На жаль, специфікація JSON не дозволяє пропускати кому. Є кілька веб-переглядачів, які це дозволять, але загалом потрібно турбуватися про всі браузери.

Як правило, я намагаюся усунути проблему і додати кому перед фактичним значенням, так що ви закінчите код, який виглядає приблизно так:

s.append("[");
for (i = 0; i < 5; ++i) {
  if (i) s.append(","); // add the comma only if this isn't the first entry
  s.appendF("\"%d\"", i);
}
s.append("]");

Цей додатковий рядок коду для циклу навряд чи дорогий ...

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

На жаль, не працює добре з масивом.


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

47
Дуже прикро, що ECMA5 визначає сліди, але JSON цього не робить.
FlavorScape

4
Так, ця зайва лінійка навряд чи дорога, але все ж неприємність.
Рене Ніффенеггер

2
Цей підхід працює для індексованих циклів. Як щодо ... стилів петель? Є елегантний спосіб?
kgf3JfUtW

2
Цей додатковий рядок коду може бути складним при роботі з властивостями. Ви можете виявити, що у вас є тони ifs, щоб уникнути цієї дурної маленької коми. Щодо дорогості YMMV, див. Це, наприклад, jsfiddle.net/oriadam/mywL9384 Пояснення: Ваше рішення чудове, я просто ненавиджу технічні характеристики, які забороняють тримати кому.
oriadam

133

Ні. Специфікація JSON, як це підтримується на веб-сайті http://json.org , не дозволяє пропускати коми. З того, що я бачив, деякі парсери можуть мовчки дозволити їх під час читання рядка JSON, а інші видаватимуть помилки. Для сумісності ви не повинні включати його.

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


1
ECMA 262 Здається, визначити це в розділі 11.1.5-Ініціалізатор об'єктів. Невже це добре чи ні, схоже, є в специфікації.
Нуль відволікання

6
Дійсність ECMAScript не обов'язково означає, що документ є дійсним. JSON - JSON, як правило, визначено в RFC 4627 , і ця специфікація не дозволяє промальовувати кому.
Тім Гілберт

1
@ZeroDistraction: ECMA262 визначає ECMAscript (також відомий як javascript), який є мовою програмування, як Perl або Ruby або C ++ або Java. JSON - це формат даних, як XML або CSV або YAML. Вони не одне і те ж. JSON не існує в EXMA262, але синтаксис, який він походить від має, і називається буквеним позначенням об'єкта (ON у JSON).
slebetman

106

Простий, дешевий, легкий для читання і завжди працює незалежно від специфікацій.

$delimiter = '';
for ....  {
    print $delimiter.$whatever
    $delimiter = ',';
}

Зайве присвоєння $ delim - це дуже мала ціна, яку потрібно заплатити. Також працює так само добре, якщо немає явного циклу, але окремих фрагментів коду.


1
Ось що я зазвичай роблю в таких ситуаціях; Я вважаю, що додаткове призначення більше ніж компенсується, усуваючи умовне, необхідне для додавання коми перед значенням в альтернативному підході ( stackoverflow.com/a/201856/8946 ).
Лоуренс Дол

5
Мені це рішення не подобається, оскільки є ще одна змінна, що забруднює мою сферу. Одне ifлегше зрозуміти. Але дякую за обмін.
Ich

3
Також краще містити область роздільника:for(let ..., sep=""; ... ; sep=",") { ...
Лоуренс Дол

1
Мені подобається такий підхід, оскільки він уникає умов, хоча сучасні процесори мають добру логіку прогнозування галузей. Дивіться також Чому швидше обробляти відсортований масив, ніж несортований масив?
Хосейн

21

Короткі коси дозволені в JavaScript, але вони не працюють в IE. Безслідна специфіка JSON Дугласа Крокфорда не дозволила їм, і оскільки це було без версії, це не повинно було змінитися. Специфікація ES5 JSON дозволила використовувати їх як розширення, але RFC 4627 Крокфорда цього не зробила, а ES5 відмовився від заборони. Firefox пішов за цим позовом. Internet Explorer - тому ми не можемо мати приємних речей.


1
Я просто спробував їх в IE 11 без проблем. У яких версіях IE ви протестували, де ви виявили, що вони можуть викликати проблеми?
іконоборство

10
Начебто Крокфорд, тому ми не можемо мати приємних речей. Це та коментарі у JSON
Hejazzman

Навіщо згадувати веб-браузери, коли ОП використовував C ++ як псевдокод? Навряд чи питання ОП стосується веб-браузерів або JavaScript.
ковбасник

@cowlinator J AVA S cript O ▪ Таблиця N otation
forresthopkinsa

1
Літеральні об’єкти Javascript надихнули формат, але JSON не для двигунів Javascript
коулінатор

13

Як уже було сказано, специфікація JSON (заснована на ECMAScript 3) не дозволяє пропускати кому. ES> = 5 це дозволяє, тому ви можете фактично використовувати цю позначення в чистому JS. Про це сперечалися, і деякі парсери його підтримували ( http://bolinfest.com/essays/json.html , http://whereswalden.com/2010/09/08/spidermonkey-json-change-trailing-commas- більше не приймається / ), але це специфіка (як показано на http://json.org/ ), що це повинен працювати в JSON. Ця річ сказала ...

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

Напр. (У псевдокоді в стилі С, подібний до запропонованого кодом OP):

s.append("[");
// MAX == 5 here. if it's constant, you can inline it below and get rid of the comparison
if ( MAX > 0 ) {
    s.appendF("\"%d\"", 0); // 0-th iteration
    for( int i = 1; i < MAX; ++i ) {
        s.appendF(",\"%d\"", i); // i-th iteration
    }
}
s.append("]");

3
Простий і швидкий зразок коду. Набагато краще, ніж пропоновані рішення інших відповідей.
Тревор Джекс

12

PHP-кодери можуть захотіти перевірити implode () . Це займає масив, приєднується до нього за допомогою рядка.

З документів ...

$array = array('lastname', 'email', 'phone');
echo implode(",", $array); // lastname,email,phone

2
Аналогічно, JavaScript має приєднатися () . Більшість мов мають подібний метод, або подібний може бути легко закодований.
Ден Бертон

16
PHP має json_encode, який обробляє всі деталі створення JSON, а не лише коми.
Brilliand

Круто! Як це стосується JSON і як це допомагає ОП у вирішенні їхнього питання? Пам'ятайте: "Чи можете ви використовувати коду в кінці об'єкта JSON?" це питання.
Rockin4Life33

7

Цікаво, що обидві C & C ++ (і я думаю, що C #, але я не впевнений) спеціально дозволяють робити кінцеву кому - саме з цієї причини: Це значно спрощує програмне створення списків. Не впевнений, чому JavaScript не дотримувався їхніх позицій.


13
ECMA чітко вказав, що проміжні коми допускаються в наступній специфікації: ejohn.org/blog/bug-fixes-in-javascript-2 Ще одна причина, щоб зрозуміти, що JSON! = JS Object.
безпліддя

PHP також дозволяє це. Я думаю, що це одна з особливостей PHP, яка мені подобається. ; p
іконоборство

4

Використовуйте JSON5. Не використовуйте JSON.

  • Об'єкти та масиви можуть мати кінцеві коми
  • Об'єктні ключі можуть бути без котирування, якщо вони є дійсними ідентифікаторами
  • Рядки можуть бути одноцитованими
  • Рядки можна розділити на кілька ліній
  • Числа можуть бути шістнадцятковими (основа 16)
  • Числа можуть починатися або закінчуватися десятковим знаком (провідним чи кінцевим).
  • Числа можуть включати нескінченність та -бесконечність.
  • Числа можуть починатися з явного знаку плюс (+).
  • Допускаються як вбудовані (однорядкові), так і блокові (багаторядкові) коментарі.

http://json5.org/

https://github.com/aseemk/json5


Виглядає добре, але не додавання нових типів даних здається упущеною можливістю ... звичайно, бажання залишатися суворим підмножиною ECMAScript 5 змушує це, але все ж ...
iconoclast

1
Також страшні міжрядкові струни. Я мрію про мультиліні ES6.
Марко Сулла

10
Ні, це ХОРОВА порада. З усіх існуючих бібліотек JSON дуже мало підтримують таке розширення; і все це для дуже сумнівних "покращень". Будь ласка, НЕ спричиняйте подальше стирання взаємодіючих можливостей завдяки таким розширеним розширенням.
StaxMan

7
Я вважаю, що витрачати своє життя на фіксацію коми - це жахливіше.
користувач619271

3

Існує можливий спосіб уникнути if-гілки в циклі.

s.append("[ "); // there is a space after the left bracket
for (i = 0; i < 5; ++i) {
  s.appendF("\"%d\",", i); // always add comma
}
s.back() = ']'; // modify last comma (or the space) to right bracket

2

Відповідно до специфікації класу JSONArray :

  • Додатковий (кома) може з’явитися безпосередньо перед дужкою, що закривається.
  • Нульове значення буде вставлено, коли є (кома) елісія.

Отже, наскільки я це розумію, слід дозволити писати:

[0,1,2,3,4,5,]

Але може статися, що деякі парсери повернуть 7 як кількість елементів (як IE8, як зазначив Даніел Ервікер) замість очікуваних 6.


Відредаговано:

Я знайшов цей валідатор JSON, який підтверджує рядок JSON щодо RFC 4627 (тип носія програми / json для нотації об’єкта JavaScript) та проти специфікації мови JavaScript. Насправді тут масив із кінцевою комою вважається дійсним лише для JavaScript, а не для специфікації RFC 4627.

Однак у специфікації RFC 4627 зазначено, що:

2.3. Масиви

Структура масиву представлена ​​у вигляді квадратних дужок, що оточують нульове або більше значень (або елементів). Елементи розділені комами.

array = begin-array [ value *( value-separator value ) ] end-array

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

PS RFC 4627 не є стандартом (як прямо вказано), і він вже використовується у RFC 7159 (що є запропонованим стандартом) RFC 7159


6
Наведене граматичне правило настільки ж точне, як ви можете отримати. Там немає ніякого способу , щоб мати value-separatorбез valueправа поряд з ним. Також текст дуже конкретний. "Розмежування значень" може застосовуватися лише за наявності кількох значень. Тож якщо у вас є два значення поруч, вони відокремлюються комою. Якщо у вас є одне значення (або якщо ви дивитесь лише на кінці значення), розділення немає, отже, і кома немає.
Steffen Heil

1

З мого минулого досвіду я виявив, що різні веб-переглядачі по-різному поводяться з косами в JSON.

І Firefox, і Chrome справляються із цим просто чудово. Але IE (Усі версії), схоже, зламаються. Я маю на увазі справді перерву і перестати читати решту сценарію.

Маючи це на увазі, а також той факт, що завжди приємно писати сумісний код, я пропоную витратити додаткові зусилля на те, щоб не було слідуючої коми.

:)


1

Я веду поточний підрахунок і порівнюю його з загальним підрахунком. Якщо кількість поточних лічильників менше загальної кількості, я показую кому.

Може не працювати, якщо у вас немає загальної кількості перед виконанням генерації JSON.

Потім знову, якщо ви використовуєте PHP 5.2.0 або вище, ви можете просто відформатувати свою відповідь за допомогою вбудованого API JSON.


1

З розслабленим JSON у вас можуть залишитися коси або просто залишити коси . Вони необов’язкові.

Для розбору документа, схожого на JSON, немає жодних причин.

Погляньте на розслаблену специфікацію JSON, і ви побачите, наскільки "шумно" оригінальна специфікація JSON. Шлях надто багато коми і цитат ...

http://www.relaxedjson.org

Ви також можете спробувати свій приклад, скориставшись цим онлайн-аналізатором RJSON, і побачити його правильний аналіз.

http://www.relaxedjson.org/docs/converter.html?source=%5B0%2C1%2C2%2C3%2C4%2C5%2C%5D


Розслаблений JSON не є JSON з технічної точки зору.
користувач2864740

Ви можете конвертувати rjson в json і з нього, тому він цілком застосований. Дуже просто додати його до свого робочого процесу.
Стівен Спунгін

Це робить припущення, що споживачі нижче за течією розуміють це не JSON. Перетворення на дійсний JSON вимагатиме видалення кома в будь-якому випадку.
користувач2864740

ОП використовує рядок для початку. Рядок може бути проаналізований json objectкористувачем JSON.parseабо бібліотекою, що використовує RJSON.parse. Я би погодився з вами, якби джерело було об’єктом, але це не так. Я не бачу, де у питанні воно взагалі згадує, що downstreamспоживає об'єкт чи рядок.
Стівен Спунгін

"Коли вручну генерується об'єкт або масив JSON , часто простіше залишити коду на останньому елементі в об'єкті або масиві. Це дозволено [ в JSON ]?" - отже, знову ж таки: хоча це цікавий альтернативний формат, він не є JSON і технічно не застосовується до питання про JSON . Немає чого захищати: це пропозиція Z поставити питання X.
user2864740

0

Зазвичай я перебираю цикл на масив і додаю кому після кожного введення рядка. Після циклу я знову видаляю останню кому.

Можливо, не найкращий спосіб, але менш дорогий, ніж перевірка кожного разу, якщо я думаю, що це останній об’єкт у циклі.


0

Це не рекомендується, але ви все одно можете зробити щось подібне для розбору.

jsonStr = '[0,1,2,3,4,5,]';
let data;
eval('data = ' + jsonStr);
console.log(data)


0

Оскільки for-цикл використовується для ітерації масиву або подібної ітерабельної структури даних, ми можемо використовувати довжину масиву, як показано,

awk -v header="FirstName,LastName,DOB" '
  BEGIN {
    FS = ",";
    print("[");
    columns = split(header, column_names, ",");
  }
  { print("  {");
    for (i = 1; i < columns; i++) {
      printf("    \"%s\":\"%s\",\n", column_names[i], $(i));
    }
    printf("    \"%s\":\"%s\"\n", column_names[i], $(i));
    print("  }");
  }
  END { print("]"); } ' datafile.txt

З datafile.txt, що містить,

 Angela,Baker,2010-05-23
 Betty,Crockett,1990-12-07
 David,Done,2003-10-31

0

Як зазначено, це заборонено. Але в JavaScript це:

var a = Array()
for(let i=1; i<=5; i++) {
    a.push(i)
}
var s = "[" + a.join(",") + "]"

(прекрасно працює в Firefox, Chrome, Edge, IE11 та без впуску в IE9, 8, 7, 5)

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.