463

When manually generating a JSON object or array, it's often easier to leave a trailing comma on the last item in the object or array. For example, code to output from an array of strings might look like (in a C++ like pseudocode):

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

giving you a string like

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

Is this allowed?

pkamb
  • 33,281
  • 23
  • 160
  • 191
Ben Combee
  • 16,831
  • 6
  • 41
  • 42
  • 78
    It was something I needed to lookup up on the web a few days ago. I didn't see an answer here on SO, so in following the mission of the site, I posed the question and answered it so others could find it. This is something Jeff explicitly said he wanted done here. – Ben Combee Oct 14 '08 at 16:16
  • 1
    With something so basic that the answer is found by looking at the official spec, this sounds more like fishing for points than providing helpful answers to unsolved problems. Sorry dude. – eyelidlessness Oct 14 '08 at 16:26
  • If it's any consolation, I didn't downvote, I just added the tag because I thought it was appropriate. – eyelidlessness Oct 14 '08 at 16:26
  • 9
    As Jeff did say, I think its perfectly fine to use SO as a 'notebook' of things that you had to spend some time looking up. Sure, this is on the simple end of those types of items, but I still think its appropriate, especially since different javascript engines will deal with this differently. – pkaeding Oct 14 '08 at 16:31
  • 3
    JSON isn't for Javascript engines, it's a universal data interchange format. There is no room for error in the answer to the question, because it's clearly specified. – eyelidlessness Oct 14 '08 at 17:09
  • Moreover, JS engines treating it differently stems from the fact that JS doesn't (currently) understand JSON and simply treats it as an object/array literal. The difference is a difference in engine treatment of object/array literals, which are *not* the same as JSON. – eyelidlessness Oct 14 '08 at 17:13
  • If JSON isn't for Javascript engines, why is it's name "JavaScript Object Notation" ? – James Curran Oct 14 '08 at 17:31
  • 2
    Because Javascript object literals inspired the format. Don't you think it's telling that JS engines are just beginning to have JSON capabilities built in? http://simonwillison.net/2006/Dec/20/json/ But JSON has many restrictions not imposed by JS, eg. JS object literals don't require quoted keys. – eyelidlessness Oct 14 '08 at 17:37
  • 2
    I removed the contrived-question tag *because* it's evident that this isn't as well-known as it ought to be, despite the fact that it's explicitly detailed in the official spec. – eyelidlessness Oct 14 '08 at 17:39
  • 7
    I was also wondering this, so it's a perfectly reasonable question. – hoju Oct 29 '09 at 05:02
  • 58
    Interestingly (or horrifyingly) in IE 8 I've just found that `alert([1, 2, 3, ].length)` will display "4". – Daniel Earwicker Mar 04 '10 at 09:36
  • 1
    In response to the idea of using SO as a social bookmark for common programming questions: what could be wrong about adding content that will inevitably bring more programmers (and their expertise) to the site? – dclowd9901 May 12 '10 at 16:55
  • 1
    For what it's worth, my complaint wasn't that the question is simple (I've gladly answered a number of simple questions here), but that it appeared (at first glance) to be a question aimed at gaming reputation points. You'll also note that I conceded the question is valid after some discussion. – eyelidlessness Feb 09 '10 at 07:47
  • 8
    Agreed that this is a good question to post. I got here by googling the question. – fool4jesus Sep 23 '11 at 15:12
  • But one more thing: why is OP MANUALLY writing out JSON? That is a clear anti-pattern -- one should always use a library for generating JSON, or converting to/from object structure that the language has. Using String concatenation is just asking for trouble; not just for commas, but for encoding, escaping, incorrect nesting. It is exactly as bad as using String manipulation or regexps for XML. – StaxMan Sep 16 '15 at 18:09
  • 1
    @DanielEarwicker: Irrelevant, since that is not JSON. – Lightness Races in Orbit Sep 17 '15 at 14:45
  • Who is Jeff? The JSON inventor? – neoexpert Jun 23 '23 at 07:33
  • This was very early in Stack Overflow's existence, and Jeff referred to Jeff Atwood, the co-CEO of the company at that time. – Ben Combee Aug 11 '23 at 19:39

21 Answers21

306

Unfortunately the JSON specification does not allow a trailing comma. There are a few browsers that will allow it, but generally you need to worry about all browsers.

In general I try turn the problem around, and add the comma before the actual value, so you end up with code that looks like this:

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("]");

That extra one line of code in your for loop is hardly expensive...

Another alternative I've used when output a structure to JSON from a dictionary of some form is to always append a comma after each entry (as you are doing above) and then add a dummy entry at the end that has not trailing comma (but that is just lazy ;->).

Doesn't work well with an array unfortunately.

chharvey
  • 8,580
  • 9
  • 56
  • 95
brianb
  • 3,510
  • 2
  • 18
  • 15
  • 3
    I've started using this formatting in all my JS code (comma before item on same line) for exactly this reason. Makes extra trailing commas much easier to spot, and saves a lot of time. It's annoying, I wish there were an option to throw an error for this with firefox (since that would help with debugging). – rocketmonkeys Aug 30 '11 at 18:16
  • Updated the answer to explicitly answer the question. I agree, my initial answer skipped the explicit, "no". – brianb May 01 '12 at 17:44
  • Is there a way to get Firefox to behave like IE in this regard, and produce an error or at least warning when a trailing comma is encountered? I develop primarily in Firefox so it would be nice to be notified of this problem as soon as possible. – Michael Butler Dec 06 '12 at 23:34
  • 71
    Its really a shame that ECMA5 specifies trailings, but JSON don't. – FlavorScape Jul 10 '13 at 00:43
  • 7
    Yes, that extra line is hardly expensive, but a nuisance nevertheless. – René Nyffenegger Oct 30 '13 at 06:57
  • Good answer. please provide "proof" (a link to docs, specs, etc.) of your answer. – chharvey Jul 03 '14 at 01:20
  • If you like obfuscated code, you can avoid the extra append thus: `s.appendF(&",\"%d\""[!i], i);`. You could simplify it to `"…" + !i`, but the compiler may warn about string arithmetic. – Marcelo Cantos Oct 25 '15 at 07:49
  • Well, now I have a task to write a syntax tree in a form of JSON while it's generated by a stack automata. I cannot use this trick unfortunately. – Calmarius Feb 07 '17 at 16:55
  • 2
    This approach works for indexed for-loops. How about for...in style loops? Is there an elegant way? – kgf3JfUtW Jun 28 '17 at 21:53
  • 2
    That extra one line of code can be complicated when dealing with properties. You may find yourself having tons of `if`s just to avoid that stupid little comma. About expensiveness YMMV, see this for example https://jsfiddle.net/oriadam/mywL9384/ Clarification: Your solution is great, I just hate specs that forbid a trailing comma. – oriadam Jul 17 '17 at 09:18
  • 1
    You can always delete the trailing comma after the loop if the array is not empty. – Petruza May 24 '19 at 15:42
  • When the conditional gets tricky, you can always build an array of strings and then `.join(",")`. – Beni Cherniavsky-Paskin Jul 15 '20 at 07:28
  • Not only browsers. Even Python package "json" does not allow trailing commas. – Daniel Chin Aug 04 '20 at 05:57
  • Why *unfortunately*? A an optional trailing comma would make the specification less clear and the syntax ambiguous in the sense of two correct expressions for the same thing. – Anton Shepelev Jan 02 '22 at 21:58
  • instead use `join(',')` – theking2 Jun 05 '22 at 21:37
147

No. The JSON spec, as maintained at http://json.org, does not allow trailing commas. From what I've seen, some parsers may silently allow them when reading a JSON string, while others will throw errors. For interoperability, you shouldn't include it.

The code above could be restructured, either to remove the trailing comma when adding the array terminator or to add the comma before items, skipping that for the first one.

Ben Combee
  • 16,831
  • 6
  • 41
  • 42
  • 1
    ECMA 262 Seems to define it in section 11.1.5-Object Initialiser. Whether or not this is good, seems to be in the spec. – Zero Distraction Apr 27 '12 at 01:56
  • 7
    Being valid ECMAScript doesn't necessarily mean a document is valid JSON - JSON is generally defined in [RFC 4627](http://www.ietf.org/rfc/rfc4627.txt), and that spec does not allow the trailing comma. – Tim Gilbert Mar 09 '13 at 04:34
  • 1
    @ZeroDistraction: ECMA262 defines ECMAscript (also known as javascript) which is a programming language like Perl or Ruby or C++ or Java. JSON is a data format like XML or CSV or YAML. They are not the same thing. JSON doesn't exist in EXMA262 but the syntax it's derived from does and it's called the Object literal notation (the ON in JSON). – slebetman May 16 '16 at 01:48
117

Simple, cheap, easy to read, and always works regardless of the specs.

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

The redundant assignment to $delim is a very small price to pay. Also works just as well if there is no explicit loop but separate code fragments.

iconoclast
  • 21,213
  • 15
  • 102
  • 138
Overflowee
  • 1,185
  • 1
  • 7
  • 2
  • 2
    That's what I typically do in situations like this; I feel the extra assignment is more than offset by eliminating the conditional needed for appending the comma before the value in the alternative approach (http://stackoverflow.com/a/201856/8946). – Lawrence Dol Jul 11 '13 at 17:05
  • 6
    I don't like this solution, as there is another variable polluting my scope. One `if` is easier to grasp. But thanks for sharing. – Ich Nov 26 '15 at 10:27
  • 4
    Also, it's better to contain the scope of the separator: `for(let ..., sep=""; ... ; sep=",") { ...` – Lawrence Dol Dec 22 '16 at 21:34
  • 1
    I like this approach because it avoid conditionals, although modern CPUs have got good branch prediction logic. See also [Why is it faster to process a sorted array than an unsorted array?](https://stackoverflow.com/questions/11227809/why-is-it-faster-to-process-a-sorted-array-than-an-unsorted-array) – Hossein Feb 13 '19 at 09:15
25

Trailing commas are allowed in JavaScript, but don't work in IE. Douglas Crockford's versionless JSON spec didn't allow them, and because it was versionless this wasn't supposed to change. The ES5 JSON spec allowed them as an extension, but Crockford's RFC 4627 didn't, and ES5 reverted to disallowing them. Firefox followed suit. Internet Explorer is why we can't have nice things.

Community
  • 1
  • 1
Tobu
  • 24,771
  • 4
  • 91
  • 98
19

As it's been already said, JSON spec (based on ECMAScript 3) doesn't allow trailing comma. ES >= 5 allows it, so you can actually use that notation in pure JS. It's been argued about, and some parsers did support it (http://bolinfest.com/essays/json.html, http://whereswalden.com/2010/09/08/spidermonkey-json-change-trailing-commas-no-longer-accepted/), but it's the spec fact (as shown on http://json.org/) that it shouldn't work in JSON. That thing said...

... I'm wondering why no-one pointed out that you can actually split the loop at 0th iteration and use leading comma instead of trailing one to get rid of the comparison code smell and any actual performance overhead in the loop, resulting in a code that's actually shorter, simpler and faster (due to no branching/conditionals in the loop) than other solutions proposed.

E.g. (in a C-style pseudocode similar to OP's proposed code):

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("]");
12

PHP coders may want to check out implode(). This takes an array joins it up using a string.

From the docs...

$array = array('lastname', 'email', 'phone');
echo implode(",", $array); // lastname,email,phone
NullUserException
  • 83,810
  • 28
  • 209
  • 234
Rik Heywood
  • 13,816
  • 9
  • 61
  • 81
  • 4
    Similarly, JavaScript has [join()](http://www.w3schools.com/jsref/jsref_join.asp). Most languages have a similar method, or a similar one can be easily coded. – Dan Burton Jun 13 '11 at 23:22
  • 18
    PHP has json_encode, which handles all the details of making JSON, not just commas. – Brilliand Mar 21 '12 at 01:53
  • 1
    That's cool! How does it apply to JSON and how does it help out the OP in a resolution to their question? Remember, "Can you use a trailing comma in a JSON object?" is the question. – Rockin4Life33 Apr 11 '20 at 02:37
  • 2
    python has join : ```','.join(mylist)``` – Loïc Sep 21 '21 at 15:23
9

Interestingly, both C & C++ (and I think C#, but I'm not sure) specifically allow the trailing comma -- for exactly the reason given: It make programmaticly generating lists much easier. Not sure why JavaScript didn't follow their lead.

James Curran
  • 101,701
  • 37
  • 181
  • 258
  • 15
    ECMA has explicitly specified that trailing commas are allowed in the upcoming spec: http://ejohn.org/blog/bug-fixes-in-javascript-2/ Yet another reason to be clear that JSON != JS Object. – eyelidlessness Oct 14 '08 at 18:20
  • PHP also allows it. I think it's the one feature of PHP that I like. ;p – iconoclast Nov 05 '14 at 19:10
9

Rather than engage in a debating club, I would adhere to the principle of Defensive Programming by combining both simple techniques in order to simplify interfacing with others:

  • As a developer of an app that receives json data, I'd be relaxed and allow the trailing comma.

  • When developing an app that writes json, I'd be strict and use one of the clever techniques of the other answers to only add commas between items and avoid the trailing comma.

There are bigger problems to be solved...

Roland
  • 4,619
  • 7
  • 49
  • 81
  • This is known as Postel's rule: https://en.wikipedia.org/wiki/Robustness_principle – Kaz Jul 29 '21 at 15:27
  • 2
    Unfortunately, it's an incredibly bad idea. You should implement specifications exactly and reject all non-conforming inputs loudly. The robustness principle leads to dozens of implementations all doing subtly different things, leading to gnashing of teeth. There are multiple ways of input being outside of a specification; no two implementors will extend in exactly the same way. Users will prepare their data against one implementation and then not have it work in another. – Kaz Jul 29 '21 at 15:30
  • This is what the Criticism section of the Wikipedia page is getting at. – Kaz Jul 29 '21 at 15:31
  • @Kaz You certainly have a point. But I get paid for developing working apps, not for apps that stop with error messages complaining about bad input. Bad? Take HTML. If browsers were strict, most sites would stop working. Oops, now I am lured into debating . . . – Roland Jul 29 '21 at 21:32
  • HTML is precisely the poster example of this. If browsers had been strict from the beginning instead of competing for rendering broken HTML, web standards would have been better off. Your front-end code wouldn't have to handle seven cases for different browsers, that you had to work out through painstaking empiricism. – Kaz Jul 29 '21 at 21:54
  • @Kaz Sure. If all browser vendors had been strict, ... that is a very big IF. I am pretty happy with the Internet today, and with no error messages in my browser. May I please be excused from this debate? I have to deliver some more working apps . . . – Roland Jul 29 '21 at 22:09
  • 2
    No problem; for even faster productivity, be sure to use a compiler that silently closes braces for you and such. – Kaz Jul 29 '21 at 22:47
6

Use JSON5. Don't use JSON.

  • Objects and arrays can have trailing commas
  • Object keys can be unquoted if they're valid identifiers
  • Strings can be single-quoted
  • Strings can be split across multiple lines
  • Numbers can be hexadecimal (base 16)
  • Numbers can begin or end with a (leading or trailing) decimal point.
  • Numbers can include Infinity and -Infinity.
  • Numbers can begin with an explicit plus (+) sign.
  • Both inline (single-line) and block (multi-line) comments are allowed.

http://json5.org/

https://github.com/aseemk/json5

user619271
  • 4,766
  • 5
  • 30
  • 35
  • Looks nice, but not adding new data types seems like a missed opportunity... of course the desire to remain a strict subset of ECMAScript 5 forces that, but still... – iconoclast Nov 05 '14 at 19:15
  • 1
    Also, mutliline strings are terrible. I dream of ES6 multilines. – Marco Sulla Jun 24 '15 at 12:43
  • 13
    No, that is HORRIBLE advice. Of all existing JSON libraries, very few support such extension; and all this for very questionable "improvements". Please do NOT cause further erosion of inter-operability by new bogus extensions like this. – StaxMan Sep 16 '15 at 18:07
  • 8
    I believe that spending your life on fixing commas is more horrible. – user619271 Sep 17 '15 at 06:57
4

No. The "railroad diagrams" in https://json.org are an exact translation of the spec and make it clear a , always comes before a value, never directly before ]:

railroad diagram for array

or }:

railroad diagram for object

Beni Cherniavsky-Paskin
  • 9,483
  • 2
  • 50
  • 58
3

There is a possible way to avoid a if-branch in the loop.

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
Zhang Boyang
  • 81
  • 1
  • 2
2

According to the Class JSONArray specification:

  • An extra , (comma) may appear just before the closing bracket.
  • The null value will be inserted when there is , (comma) elision.

So, as I understand it, it should be allowed to write:

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

But it could happen that some parsers will return the 7 as item count (like IE8 as Daniel Earwicker pointed out) instead of the expected 6.


Edited:

I found this JSON Validator that validates a JSON string against RFC 4627 (The application/json media type for JavaScript Object Notation) and against the JavaScript language specification. Actually here an array with a trailing comma is considered valid just for JavaScript and not for the RFC 4627 specification.

However, in the RFC 4627 specification is stated that:

2.3. Arrays

An array structure is represented as square brackets surrounding zero or more values (or elements). Elements are separated by commas.

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

To me this is again an interpretation problem. If you write that Elements are separated by commas (without stating something about special cases, like the last element), it could be understood in both ways.

P.S. RFC 4627 isn't a standard (as explicitly stated), and is already obsolited by RFC 7159 (which is a proposed standard) RFC 7159

Community
  • 1
  • 1
Timoty Weis
  • 180
  • 2
  • 9
  • 8
    The grammar rule given is as precise as you can get. There is no way to have a `value-separator` without a `value` right next to it. Also the text is very specific. "Separation of values" can only apply if there are multiple values. So if you have two values next to each other, they are separated using a comma. If you have one value (or if you only look at the value at the end), there is no separation, hence no comma. – Steffen Heil Feb 12 '16 at 13:49
  • Your sample contains 7 elements, 6 typed integer one void. Stop thinking of this as "trailing" , but more as expressions allowing to be empty or not. Coming from a history of parser building this is really the issue here how many elements in [0, , , ] ? One or four? – theking2 Jul 20 '21 at 20:03
1

It is not recommended, but you can still do something like this to parse it.

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

With Relaxed JSON, you can have trailing commas, or just leave the commas out. They are optional.

There is no reason at all commas need to be present to parse a JSON-like document.

Take a look at the Relaxed JSON spec and you will see how 'noisy' the original JSON spec is. Way too many commas and quotes...

http://www.relaxedjson.org

You can also try out your example using this online RJSON parser and see it get parsed correctly.

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

Steven Spungin
  • 27,002
  • 5
  • 88
  • 78
  • Relaxed JSON is not JSON so- technically non-applicable. – user2864740 Nov 26 '18 at 21:51
  • You can convert rjson to and from json, so it is totally applicable. Very easy to add it to your workflow too. – Steven Spungin Nov 26 '18 at 22:22
  • This makes the assumption that downstream consumers understand this not-JSON. Converting to valid JSON would require removing the comma in either case. – user2864740 Nov 26 '18 at 22:33
  • OP uses a string to start with. The string may be parsed to a `json object` using `JSON.parse`, or by a library using `RJSON.parse`. I would agree with you if the source was an object, but that’s not the case here. I do not see where in the question it mentions `downstream` at all consuming an object or string. – Steven Spungin Nov 27 '18 at 01:32
  • "When manually generating a *JSON* object or array, it's often easier to leave a trailing comma on the last item in the object or array.. Is this allowed [*in JSON*]?" - so, again: while this is an interesting alternative format, it is is *not JSON* and not technically applicable to the question about *JSON*. There is nothing to 'defend': it's a Z proposal to question X. – user2864740 Nov 27 '18 at 03:22
1

As stated it is not allowed. But in JavaScript this is:

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

(works fine in Firefox, Chrome, Edge, IE11, and without the let in IE9, 8, 7, 5)

theking2
  • 2,174
  • 1
  • 27
  • 36
0

I keep a current count and compare it to a total count. If the current count is less than the total count, I display the comma.

May not work if you don't have a total count prior to executing the JSON generation.

Then again, if your using PHP 5.2.0 or better, you can just format your response using the JSON API built in.

Animism
  • 496
  • 4
  • 10
eddie
  • 9
  • 1
0

Since a for-loop is used to iterate over an array, or similar iterable data structure, we can use the length of the array as shown,

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

With datafile.txt containing,

 Angela,Baker,2010-05-23
 Betty,Crockett,1990-12-07
 David,Done,2003-10-31
0
String l = "[" + List<int>.generate(5, (i) => i + 1).join(",") + "]";
0

Using a trailing comma is not allowed for json. A solution I like, which you could do if you're not writing for an external recipient but for your own project, is to just strip (or replace by whitespace) the trailing comma on the receiving end before feeding it to the json parser. I do this for the trailing comma in the outermost json object. The convenient thing is then if you add an object at the end, you don't have to add a comma to the now second last object. This also makes for cleaner diffs if your config file is in a version control system, since it will only show the lines of the stuff you actually added.

    char* str = readFile("myConfig.json");
    char* chr = strrchr(str, '}') - 1;
    int i = 0;
    while( chr[i] == ' ' || chr[i] == '\n' ){
        i--;
    }
    if( chr[i] == ',' ) chr[i] = ' ';
    JsonParser parser;
    parser.parse(str);

Qwert Yuiop
  • 105
  • 1
  • 11
0

From my past experience, I found that different browsers deal with trailing commas in JSON differently.

Both Firefox and Chrome handles it just fine. But IE (All versions) seems to break. I mean really break and stop reading the rest of the script.

Keeping that in mind, and also the fact that it's always nice to write compliant code, I suggest spending the extra effort of making sure that there's no trailing comma.

:)

dnshio
  • 914
  • 1
  • 8
  • 21
-1

I usually loop over the array and attach a comma after every entry in the string. After the loop I delete the last comma again.

Maybe not the best way, but less expensive than checking every time if it's the last object in the loop I guess.

Nils
  • 13,319
  • 19
  • 86
  • 108