Encoding symbol keys in JSON?

# Alex Vincent (3 months ago)

In modern ECMAScript, objects can have symbols for property names instead of strings. This leads me to a problem in my es7-membrane project: how do I translate those symbol keys into JSON for a reusable file? (I partially answer my own question below.)

Consider the following code:

const X = {}; const two = Symbol("two"); Reflect.defineProperty(X, "one", {value: 1, writable: true, enumerable: true, configurable: true}); Reflect.defineProperty(X, two, {value: 2, writable: true, enumerable: true, configurable: true}); return JSON.stringify(Reflect.ownKeys(X));

In both Mozilla Firefox and Google Chrome, this returns ["one", null]. I suppose this is part of the ECMAScript's latest standard. I do see JSON.stringify has a "replacer" callback argument, and JSON.parse has a "reviver" argument. I presume that these are here to solve encoding/decoding problems with JSON. This may be the route I take...

At first, serializing shouldn't be a problem: if I hit a symbol as a key, I could use the replacer functionality to deliver a standard JSON-serializable object.

But what if the ordering of keys is not guaranteed? I'm referring specifically to the case of a developer modifying X's properties in the above snippet - say, by defining Symbol("three") as a key before the two key. Or worse, by defining a different Symbol("two") before the existing two key? I am not referring to the case of the developer modifying the results from Result.ownKeys().

Now, all of a sudden, this little stringify problem has possibly morphed into a diff/merge problem: between yesterday's serialized JSON for ownKeys and today's, someone has cleverly inserted a symbol where there was another in the list of keys. My code is supposed to infer today from yesterday's generated JSON which property key belongs to which property value. With symbols - especially identically-keyed symbols - I could lose that consistency if I'm not careful.

(Side note: for es7-membrane, I faced a similar but easily solvable problem, where Reflect.ownKeys(function() {}) returned different results in different browsers - especially when the function passed into ownKeys had additional properties. In that case all the properties were strings, so I just extracted the common set of string-named properties and put them at the front of the keys list for consistency.)

I'm looking for advice - including the very real possibility that I'm overthinking this or worrying too much about an edge case.

# Isiah Meadows (3 months ago)

I honestly wouldn't worry about this edge case - it's rare you actually would want to serialize symbols, and it's usually best handled at the application level, not the framework level.

# Allen Wirfs-Brock (3 months ago)