Можете ли вы использовать запятую в 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("]");

Эта лишняя строка кода в вашем цикле for вряд ли стоит дорого ...

Другая альтернатива, которую я использовал при выводе структуры в JSON из словаря некоторой формы, - это всегда добавлять запятую после каждой записи (как вы делаете выше), а затем добавлять фиктивную запись в конце, которая не имеет запятой (но не запаздывает). это просто лень; ->).

К массиву не работает, к сожалению.

brianb
источник
2
Именно по этой причине я начал использовать это форматирование во всем своем коде JS (запятая перед элементом в той же строке). Делает дополнительные запятые намного проще и экономит много времени. Это раздражает, я хотел бы, чтобы была возможность выдать ошибку для Firefox (так как это помогло бы с отладкой).
rocketmonkeys
47
Жаль, что ECMA5 определяет трейлинги, а JSON - нет.
FlavorScape
4
Да, эта дополнительная линия вряд ли стоит дорого, но, тем не менее, неприятность.
Рене Ниффенеггер,
2
Этот подход работает для индексированных циклов for. Как насчет ... в стиле петли? Есть ли элегантный способ?
kgf3JfUtW
2
Эта лишняя строка кода может быть сложной при работе со свойствами. Вы можете найти тонны ifs просто чтобы избежать этой глупой маленькой запятой. Что касается дороговизны YMMV, см. Это, например, jsfiddle.net/oriadam/mywL9384. Разъяснение: Ваше решение великолепно, я просто ненавижу спецификации, которые запрещают запятую в конце.
Ориадам
133

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

Приведенный выше код можно реструктурировать, либо удалить запятую при добавлении терминатора массива, либо добавить запятую перед элементами, пропустив ее для первого.

Бен Комби
источник
1
ECMA 262 Кажется, чтобы определить это в разделе 11.1.5-Object Initializer. Хорошо это или нет, похоже, в спецификации.
Ноль отвлечение
6
Наличие действительного ECMAScript не обязательно означает, что документ является допустимым JSON - JSON обычно определяется в RFC 4627 , и эта спецификация не допускает конечную запятую.
Тим Гилберт
1
@ZeroDistraction: ECMA262 определяет ECMAscript (также известный как javascript), который является языком программирования, таким как Perl или Ruby или C ++ или Java. JSON - это формат данных, такой как XML, CSV или YAML. Они не одно и то же. JSON не существует в EXMA262, но синтаксис, на основе которого он создан, называется литеральной нотацией Object (ON в JSON).
Slebetman
106

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

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

Избыточное присвоение $ delim - очень маленькая цена. Также работает так же хорошо, если нет явного цикла, но есть отдельные фрагменты кода.

Overflowee
источник
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 - вот почему у нас не может быть хороших вещей.

Tobu
источник
1
Я просто попробовал их в IE 11 без проблем. В каких версиях IE вы тестировали, где вы обнаружили, что они вызывают проблемы?
иконоборчество
10
Похоже, Крокфорд - вот почему у нас не может быть хороших вещей. Это и комментарии в JSON
Hejazzman
Зачем упоминать веб-браузеры, когда OP использует C ++, как псевдокод? Вряд ли вопрос ОП связан с веб-браузерами или JavaScript.
Cowlinator
@cowlinator J AVA S cript O ▪ Таблица N otation
forresthopkinsa
1
Формат литералов объектов Javascript вдохновил формат, но JSON не для движков Javascript
cowlinator
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-й итерации и использовать начальную запятую вместо конечной, чтобы избавиться от запаха кода сравнения и любых фактических издержек производительности в цикле, что приведет к код, который на самом деле короче, проще и быстрее (из-за отсутствия ветвления / условных обозначений в цикле), чем другие предлагаемые решения.

Например (в псевдокоде в стиле C, аналогичном предлагаемому коду 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 имеет join () . У большинства языков есть подобный метод, или подобный может быть легко закодирован.
Дэн Бертон
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

user619271
источник
Выглядит хорошо, но не добавление новых типов данных кажется упущенной возможностью ... конечно, желание остаться строгим подмножеством ECMAScript 5 заставляет это, но все же ...
iconoclast
1
Кроме того, мутлиновые строки ужасны. Мечтаю о мультилине ES6.
Марко Сулла
10
Нет, это ужасный совет. Из всех существующих библиотек JSON очень немногие поддерживают такое расширение; и все это для очень сомнительных "улучшений". Пожалуйста, НЕ вызывайте дальнейшего разрушения совместимости новыми поддельными расширениями, подобными этому.
StaxMan
8
Я считаю, что тратить свою жизнь на исправление запятых ужаснее.
user619271
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 :

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

Итак, насколько я понимаю, нужно разрешить написать:

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

Но может случиться так, что некоторые парсеры вернут 7 как количество элементов (как IE8, как указал Дэниел Эрвикер) вместо ожидаемых 6.


Отредактировано:

Я нашел этот JSON Validator, который проверяет строку JSON по RFC 4627 (тип носителя application / 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права рядом с ним. Также текст очень специфичен. «Разделение значений» может применяться только при наличии нескольких значений. Так что если у вас есть два значения рядом друг с другом, они разделяются запятой. Если у вас есть одно значение (или если вы смотрите только на значение в конце), разделение отсутствует, следовательно, нет запятой.
Штеффен Хейл
1

Исходя из прошлого опыта, я обнаружил, что разные браузеры по-разному обрабатывают конечные запятые в JSON.

И Firefox, и Chrome отлично с этим справляются. Но IE (все версии), кажется, сломался. Я имею в виду действительно сломать и перестать читать остальную часть сценария.

Учитывая это, а также тот факт, что всегда приятно писать совместимый код, я предлагаю потратить дополнительные усилия, чтобы убедиться, что нет запятой.

:)

dnshio
источник
1

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

Может не работать, если у вас нет общего количества до выполнения генерации JSON.

Опять же, если вы используете PHP 5.2.0 или выше, вы можете просто отформатировать свой ответ, используя встроенный JSON API.

Эдди
источник
1

С Relaxed JSON вы можете использовать запятые или просто оставлять их запятыми . Они не являются обязательными.

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

Посмотрите на спецификацию Relaxed JSON, и вы увидите, насколько «шумна» оригинальная спецификация JSON. Слишком много запятых и цитат ...

http://www.relaxedjson.org

Вы также можете попробовать свой пример с помощью этого онлайн-анализатора RJSON и убедиться, что он анализируется правильно.

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

Стивен Спунгин
источник
Расслабленный JSON не является технически неприменимым.
user2864740
Вы можете конвертировать RJSON в и из JSON, так что это полностью применимо. Очень легко добавить его в свой рабочий процесс тоже.
Стивен Спунгин
Это делает предположение, что нижестоящие потребители понимают это не-JSON. Преобразование в действительный JSON потребует удаления запятой в любом случае.
user2864740
OP использует строку для начала. Строка может быть проанализирована с json objectиспользованием JSON.parseили с использованием библиотеки RJSON.parse. Я бы согласился с вами, если бы источником был объект, но здесь это не так. Я не вижу, где в вопросе downstreamвообще упоминается, что он потребляет объект или строку.
Стивен Спунгин
«При создании вручную объекта или массива JSON часто проще оставить запятую на последнем элементе в объекте или массиве. Это разрешено [ в JSON ]?» Итак, еще раз: хотя это интересный альтернативный формат, он не является JSON и технически не применим к вопросу о JSON . Там нет ничего, чтобы «защищать»: это предложение Z на вопрос X.
user2864740
0

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

Возможно, не лучшим способом, но менее дорогим, чем проверка каждый раз, если это последний объект в цикле, я думаю.

Nils
источник
0

Это не рекомендуется, но вы все равно можете сделать что-то подобное, чтобы разобрать это.

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

feibing
источник
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
Грегори Хорн 07AD
источник
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)

theking2
источник