Можете ли вы использовать конечную запятую в объекте JSON?

При ручной генерации объекта или массива JSON часто проще оставить запятую в последнем элементе объекта или массива. Например, код для вывода из массива строк может выглядеть следующим образом (в псевдокоде C++):

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

давая вам строку, как

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

Это разрешено?

Ответ 1

К сожалению спецификация 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 for download не стоит дорого...

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

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

Ответ 2

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

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

Ответ 3

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

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

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

Ответ 4

В JavaScript разрешены запятые запятые, но не работают в IE. Douglas Crockford безрезультатный JSON spec не позволял им, и поскольку он был бездействующим, это не должно меняться. Спецификация ES5 JSON разрешала им расширение, но Crockford RFC 4627 не было, и ES5 вернулась к отказу от них. Firefox последовал примеру. Internet Explorer - это то, почему у нас не может быть приятных вещей.

Ответ 5

PHP-кодеры могут захотеть проверить implode(). Это берет массив, соединяющий его, используя строку.

Из docs...

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

Ответ 6

Как уже было сказано, спецификация JSON (основанная на ECMAScript 3) не допускает запятой в конце. ES> = 5 позволяет, так что вы можете использовать эту запись в чистом JS. Об этом спорили, и некоторые парсеры действительно поддерживали его (http://bolinfest.com/essays/json.html, http://whereswalden.com/2010/09/08/spidermonkey-json-change-trailing-commas-no-longer-accepted/), но это тот конкретный факт (как показано на http://json.org/), что он не должен работать в JSON. Эта вещь сказала...

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

Например. (в псевдокоде в стиле C, аналогичном предлагаемому коду OP):

s.append("[");
// MAX == 5 here. if it 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("]");

Ответ 7

Интересно, что как C, так и С++ (и я думаю, что С#, но я не уверен), специально разрешить конечную запятую - именно по этой причине: Сделать программным способом генерировать списки намного проще. Не уверен, почему JavaScript не последовал их примеру.

Ответ 8

Использовать JSON5. Не используйте JSON.

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

http://json5.org/

https://github.com/aseemk/json5

Ответ 9

В соответствии с спецификацией класса JSONArray:

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

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

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

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


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

Я нашел этот JSON Validator, который проверяет строку JSON на RFC 4627 (Тип приложения /json для нотации объектов JavaScript) и спецификации языка JavaScript. Фактически здесь массив с конечной запятой считается действительным только для JavaScript, а не для спецификации RFC 4627.

Однако в спецификации RFC 4627 указано, что:

2,3. Массивы

Структура массива представляется как квадратные скобки, окружающие нуль или больше значений (или элементов). Элементы разделяются запятыми.

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

Для меня это снова проблема интерпретации. Если вы напишете, что Элементы разделены запятыми (не указывая что-то о специальных случаях, как последний элемент), это можно понять в обоих направлениях.

P.S. RFC 4627 не является стандартом (как явно указано), и он уже обменивается RFC 7159 (который является предлагаемым стандартом) RFC 7159

Ответ 10

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

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

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

Ответ 11

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

Оба Firefox и Chrome обрабатывают его просто отлично. Но IE (все версии), похоже, ломаются. Я имею в виду действительно разорвать и перестать читать остальную часть script.

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

:)

Ответ 12

С 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

Ответ 13

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

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

Ответ 14

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

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

Ответ 15

Существует возможный способ избежать ветвления 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

Ответ 16

Поскольку цикл 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