Closed willemt closed 4 years ago
Thanks for the suggestion, and thanks for opening this issue in the correct repository.
There was discussion on this a long time ago. At that time, we decided not to implement this feature. I'm not opposed to revisiting this idea, but I do have some reservations.
I've quoted some of the original discussion here as this is the proper place to continue discussion.
ES5 supports numeric literals as property names in object literals. [ES5 §11.1.5]
This allows productions like:
{ 1 : 'int',
.2 : 'float',
3. : 'trailing dec',
4e-2 : 'exp',
0x50 : 'hex' }
All property names are normalized to strings. So the above will result in:
{ '1' : 'int',
'3' : 'trailing dec',
'80' : 'hex',
'0.2' : 'float',
'0.04' : 'exp' }
Note that the definition of numeric literal precludes signed numbers and special IEEE 754 values, so the following productions are either errors or not treated as numeric values.
{ -1 : 'neg (error)',
+1 : 'pos (error)',
Infinity : 'inf (valid but parsed as identifier)',
-Infinity : 'neg inf (error)',
NaN : 'not a num (valid but parsed as identifier)' }
Are there plans to support the same syntax that ES5 does? I don't see floating points used as property names very often, but I can see decimal and hexadecimal integers being useful.
I couldn't find any rationale in ES5 as to why this is allowed. I think it's more of a convenience thing. I can see where it could make your code cleaner, especially if you want to store a hash table using hexadecimal numbers as keys.
// ELF header
// Source: http://en.wikipedia.org/wiki/Executable_and_Linkable_Format#File_layout
// { offset : fieldName }
{ 0x00 : 'EI_MAG0',
0x04 : 'EI_CLASS',
0x05 : 'EI_DATA',
0x06 : 'EI_VERSION',
0x07 : 'EI_OSABI',
0x08 : 'EI_ABIVERSION',
... }
But this brings with it at least two issues that come to mind:
1
, 1.
, 1.0
, 1.00
, 1e0
, 1e-0
, 1e+0
, 1.e0
, 1.0e0
, 0x1
, 0x01
, ad infinitum all get stored as '1'
in the object, and as such will overwrite each other.JSON5.stringify
must either:
Another thing to consider is interoperability. In many languages, JSON objects are represented as dictionaries or associative arrays with string keys. However, those languages also support numeric keys.
JavaScript
const hash = {123: 'abc'}
hash[123] // returns 'abc'
hash['123'] // returns 'abc'
Ruby
hash = {123 => 'abc'}
hash[123] # returns 'abc'
hash['123'] # returns nil (Ruby's version of null)
Python
hash = {123: 'abc'}
hash[123] # returns 'abc'
hash['123'] # throws KeyError
C#
var hash = new Dictionary<int, object> { { 123, "abc" } }
hash[123] // returns "abc"
hash["123"] // compilation error
So how do these languages treat the JSON5 document {123:'abc'}
? Is it a hash table with integer keys or string keys? If the keys are integers, then what happens when you mix key types?
{
123: 'abc',
'a wild string appears': "it's not very effective"
}
If the language treats all keys as strings, then you run into the issue of normalizing those numbers as strings.
{ 1 : 'int',
.2 : 'float',
3. : 'trailing dec',
4e-2 : 'exp',
0x50 : 'hex' }
becomes
{ '1' : 'int',
'0.2' : 'float',
'3' : 'trailing dec',
'0.04' : 'exp',
'80' : 'hex' }
and the keys have to be converted back into numbers after they've been parsed if you actually wanted numeric keys.
ES5 supports numeric literals as property names in object literals. [...] All property names are normalized to strings
The conversion from numbers to strings is lossy.
While this may be convenient in JS at times, when it comes to a data storage/transport format, this could lead to some extremely unpredictable bugs.
In my optic, this sort of thing is unprecedented in JSON, which doesn't do any other type-conversions on the fly - I think that's one of the reasons JSON is very safe and reliable as a data format; probably also why implementations among platforms very rarely have bugs.
In my opinion, if (as a user of a JSON5 library) you wanted a "number-looking string" key, then use a string key - it's much safer for you to own the responsibility of converting your numbers to/from strings, as, for one, conversion facilities can behave very differently among platforms.
I think this is necessary, I need sparse array., because of this, I use json-z for the following syntax:
[.1, .1,,, .1, 10: .1, "100000": .1]
As the title is integers as key, those floating point name, engineering numeric should be ignore. JSON = Javascript Object Notation, other languages such as Ruby/C#/Python should comply to Javascript Object Notation behavior for interoperability .
Is a key with plus sign valid, like one+two: "three"
?
Is a key with plus sign valid, like
one+two: "three"
?
No, it is not valid ES5 nor JSON5.
In JSON keys MUST be strings. It would be handy if it was possible to use integers as keys like so:
Example usecase I have a REST service that represents assignments between objects like below. It would be better if the REST service could use integers instead of strings for keys.