That is legitimate JSON:
“a”: 1,
“b”: 2,
“c”: 3
}
That is invalid JSON:
“a”: 1,
“b”: 2,
“c”: 3,
}
The distinction is the final comma. The JSON grammar specifies {that a} comma can separate two members of an object however not postcede (“path”) a member. I believe this was a design mistake. Say we wish to add two new keys to the struct, one earlier than the “a” member and one after the “c” member. This is what it will seem like if trailing commas had been permitted:
+ “x”: 0,
“a”: 1,
“b”: 2,
“c”: 3,
+ “y”: 4,
}
It is the very same textual content transformation no matter the place we add the important thing. Within the present mannequin, we as a substitute have this:
+ “x”: 0,
“a”: 1,
“b”: 2,
– “c”: 3
+ “c”: 3,
+ “y”: 4
}
These are totally different transformations! Equally if you wish to take away a component, you’ll be able to’t simply delete the corresponding line, you must delete the road after which verify that the final line would not have a trailing comma. Do not even get me began on all of the particular instances concerned in swapping two strains.
JSON is not the one language with this downside. Haskell writes file varieties like this:
knowledge Drone = Drone
{ xPos :: Int
, yPos :: Int
, zPos :: Int
}
This “partial bullet level” model of placing separators in the beginning of rows makes it simpler to alter the final row however tougher to alter the primary one.
TLA+ has this downside too:
This one’s annoying as a result of 1) you are always including new top-level variables whereas engaged on a spec and a pair of) the PlusCal DSL doesn’t have this downside:
(*–algorithm foo {
variables a; b; c;
The worst offenders, IMO, are logic languages like Prolog. Not solely do not you might have trailing separators, you might have a particular terminating image:
A = 1, % comma
B = 2, % comma
C = 3. % interval!
I assume you’ll be able to type of consider it as funny-lookin’ braces:
A = 1,
B = 2,
C = 3
.
However this isn’t normal syntax and folks will take a look at you bizarre in the event you attempt it. And you continue to do not get trailing separators.
One thing higher
Some languages permit trailing separators:
legitimate := map[string]int{
“a”: 1,
“b”: 2,
“c”: 3,
}
legitimate = {
“a”: 1,
“b”: 2,
“c”: 3,
}
However I believe we will do one higher than that. Python and Go commas can path however not lead, which means we won’t go 100% bullet factors:
invalid = {
, “a”: 1
, “b”: 2
, “c”: 3
}
Now I personally assume that bullet factors are the bee’s knees and want extra languages allowed main separators. TLA+ truly has main conjunction and disjunction operations:
|| && a == 1
&& b == 2
|| && a == 3
&& b == 4
You may’t path these, although, no writing (a &&).
Essentially the most versatile I’ve seen is Alloy, which permits each main and trailing commas:
sig Legitimate {
, a: 1
, b: 2
}
sig AlsoValid {
a: 1,
b: 2,
}
Alloy does go slightly power-mad right here, as a result of it additionally permits empty separators.
,, a: 1,,
,,,,,,,,,
,, b: 2,,
}
I’ve heard some individuals name this “stuttering”. I am unable to determine how one can commit crimes with this however you by no means know.
Satan’s advocate
One argument in opposition to trailing separators is that they make parsing ambiguous. Think about this Prolog:
A = 1,
B = 2.
bar(c).
Right here it is fairly clear that foo and bar are separate definitions. But when we substitute the rule terminator with commas:
A = 1,
B = 2,
bar(c),
Now it might be alternatively parsed that bar(c) is a part of the definition of foo— foo is just true when bar(c) can be true.
As one other instance, that is legitimate Ruby:
places 3.
succ().
succ()
If we may “path technique calls”, that is ambiguous:
bar().
baz().
quux()
Now it isn’t clear if quux() is a top-level perform or a way of foo.
Each of these relate to regulate separators, not knowledge separators. Python has an edge knowledge case with trailing knowledge separators. The language makes use of parenthesis each for expression grouping like (2+3) and for tuple definition like (2,3). So how do you distinguish an expression analysis from a single-element tuple? With a trailing comma!
>>> kind(x)
>>> x = (2+3,)
>>> kind(x)
Okay that is all I received. New (and remaining) preview launch of Logic for Programmers subsequent week.

