436

手动生成 JSON 对象或数组时,通常更容易在对象或数组的最后一项上留下逗号。例如,从字符串数组输出的代码可能如下所示(在类似 C++ 的伪代码中):

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

给你一个字符串

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

这是允许的吗?

4

19 回答 19

285

不幸的是,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 输出结构时,我使用的另一种替代方法是始终在每个条目后附加一个逗号(如您在上面所做的那样),然后在末尾添加一个没有尾随逗号的虚拟条目(但是那只是懒惰;->)。

不幸的是,它不适用于数组。

于 2008-10-14T16:19:55.650 回答
139

不可以。在http://json.org维护的 JSON 规范不允许尾随逗号。据我所见,一些解析器在读取 JSON 字符串时可能会默默地允许它们,而其他解析器会抛出错误。为了互操作性,您不应包含它。

上面的代码可以重新构造,或者在添加数组终止符时删除尾随逗号,或者在项目之前添加逗号,跳过第一个。

于 2008-10-14T16:02:34.530 回答
114

简单,便宜,易于阅读,并且无论规格如何都始终有效。

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

对 $delim 的冗余分配是一个非常小的代价。如果没有显式循环但单独的代码片段也同样有效。

于 2011-12-16T07:38:36.850 回答
23

JavaScript 中允许使用尾随逗号,但在 IE 中不可用。Douglas Crockford 的无版本 JSON 规范不允许它们,因为它是无版本的,所以不应该改变。ES5 JSON 规范允许它们作为扩展,但 Crockford 的RFC 4627没有,并且 ES5 恢复为不允许它们。Firefox紧随其后。Internet Explorer 是我们无法拥有美好事物的原因。

于 2012-07-15T20:18:18.400 回答
16

正如已经说过的,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 次迭代时拆分循环并使用前导逗号而不是尾随逗号来消除比较代码气味和循环中的任何实际性能开销,从而导致与提出的其他解决方案相比,代码实际上更短、更简单和更快(由于循环中没有分支/条件)。

例如(在类似于 OP 提议的代码的 C 风格的伪代码中):

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("]");
于 2014-04-12T17:06:51.343 回答
11

PHP 编码人员可能想查看implode()。这需要一个数组使用字符串将其连接起来。

文档...

$array = array('lastname', 'email', 'phone');
echo implode(",", $array); // lastname,email,phone
于 2008-10-16T07:26:38.813 回答
9

有趣的是,C 和 C++(我认为是 C#,但我不确定)都特别允许尾随逗号 - 正是因为给出的原因:它使以编程方式生成列表变得更加容易。不知道为什么 JavaScript 没有跟随他们的领导。

于 2008-10-14T17:29:36.193 回答
6

使用 JSON5。不要使用 JSON。

  • 对象和数组可以有尾随逗号
  • 如果对象键是有效标识符,则可以不加引号
  • 字符串可以单引号
  • 字符串可以分成多行
  • 数字可以是十六进制(以 16 为基数)
  • 数字可以以(前导或尾随)小数点开始或结束。
  • 数字可以包括 Infinity 和 -Infinity。
  • 数字可以以明确的加号 (+) 开头。
  • 内联(单行)和块(多行)注释都是允许的。

http://json5.org/

https://github.com/aseemk/json5

于 2014-08-24T07:35:55.217 回答
4

我不会参加辩论俱乐部,而是申请Defensive Programming并利用这两种技术:

  • 作为接收json 数据的应用程序的开发人员,我会放松允许尾随逗号。

  • 在开发编写json的应用程序时,我会很严格,并使用其他答案中的一种巧妙技术,仅在项目之间添加逗号并避免尾随逗号。

还有更大的问题需要解决……

于 2020-09-25T14:13:03.573 回答
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
于 2018-11-18T15:00:52.390 回答
3

不。https://json.org中的“铁路图”是规范的精确翻译,并明确表示 a,总是出现在 a 之前value,而不是直接在之前]

阵列的铁路图

}

对象的铁路图

于 2020-07-15T07:35:54.273 回答
2

根据Class JSONArray 规范

  • 额外的 ,(逗号)可能出现在右括号之前。
  • 当存在 ,(逗号)省略时,将插入空值。

所以,据我了解,它应该被允许写成:

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

但可能会发生某些解析器将 7 作为项目计数返回(如 Daniel Earwicker 指出的 IE8)而不是预期的 6。


编辑:

我发现这个JSON Validator根据RFC 4627(JavaScript Object Notation 的应用程序/json 媒体类型)和 JavaScript 语言规范验证 JSON 字符串。实际上,此处带有尾随逗号的数组被认为仅对 JavaScript 有效,而对 RFC 4627 规范无效。

但是,在 RFC 4627 规范中声明:

2.3. 数组

数组结构表示为围绕零个或多个值(或元素)的方括号。元素用逗号分隔。

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

对我来说,这又是一个解释问题。如果你写元素是用逗号分隔的(没有说明一些特殊情况,比如最后一个元素),它可以用两种方式来理解。

PS RFC 4627 不是标准(如明确说明的那样),并且已被 RFC 7159(这是一个提议的标准)RFC 7159 废弃

于 2015-04-22T09:14:09.063 回答
1

不推荐,但你仍然可以做这样的事情来解析它。

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

于 2017-11-01T21:35:40.897 回答
1

使用轻松 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

于 2018-02-08T02:05:49.810 回答
1

如前所述,这是不允许的。但在 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 中没有 let)

于 2019-11-15T13:47:54.597 回答
0

我保留当前计数并将其与总计数进行比较。如果当前计数小于总计数,则显示逗号。

如果您在执行 JSON 生成之前没有总计数,则可能无法工作。

再说一次,如果您使用 PHP 5.2.0 或更高版本,您可以使用内置的 JSON API 格式化您的响应。

于 2010-11-11T21:26:29.527 回答
0

根据我过去的经验,我发现不同的浏览器以不同的方式处理 JSON 中的尾随逗号。

Firefox 和 Chrome 都处理得很好。但 IE(所有版本)似乎坏了。我的意思是真的打破并停止阅读脚本的其余部分。

牢记这一点,以及编写兼容代码总是很好的事实,我建议花额外的精力确保没有尾随逗号。

:)

于 2011-10-14T15:59:24.593 回答
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
于 2019-03-01T03:34:54.607 回答
-1

我通常遍历数组并在字符串中的每个条目后附加一个逗号。在循环之后,我再次删除最后一个逗号。

也许不是最好的方法,但比每次检查它是否是我猜的循环中的最后一个对象要便宜。

于 2008-12-11T10:06:49.620 回答