- Published on
RAMSON, part 1
- Authors
- Name
- Ian Atha
- @IanAtha
RAMSON is a JSON schema that serializes and deserializes JS/ECMAScript objects precisely as they were in memory.
For example, consider the following Javascript code:
var state = { foo: 1 };
var root = { a: state, b: state };
root.a
and root.b
refer to the same object. To convince yourself experimentally, try:
root.a.foo = root.a.foo + 1; // update root.a
console.log(root.b.foo); // observe that root.b also changed
You'll notice that the output is 2
.
However, if we were to use JSON to serialize and deserialize root
, root.a
and root.b
would no longer be the same object: setting root.a.foo
would no longer be reflected when reading root.b.foo
.
A Naive Solution
A naive approach to solving this is to assign tags to each value as we encounter them.
First, let use define that:
,
Now, we can implement:
returns a monotonically incrementing number for every new ,
Specifically, for each value v
, that's being serialized:
- if
v
, is of type string, number, boolean, undefined, or null, serialize it as is, - if
v
, has no previously assigned reftag, assign one, and serialize the value including an extrareftag
field 1, - if
v
, has a reftag, serialize only a reference to the reftag asreftag
, eluding the actual value.
A reftag
(reference tag) can be any string or numerical identifier that uniquely identifies an instance of an object. For example, one could use the actual memory address of the value in the JS interpreters memory, or just an incremental counter.
Example
For example, the root
object from the aforementioned example could become:
{ "a": { "$$tag_def": 1, "foo": 1 }, "b": { "$$tag_ref": 1 } }
Recursive Objects
Consider that we also set root.self_ref = root
. Whereas JSON.stringify
would throw a "Converting circular structure to JSON" error, RAMSON would serialize it as
{ "$$def_reftag": 1, "a": { "$$def_reftag": 2, "foo": 1 }, "b": { "$$ref_reftag": 2 }, "self_ref": { "$$ref_reftag": 1 } }
Further work
This initial draft only covers strings, numbers, booleans, undefined, null, and objects. Given this, arrays are also trivial, but require fine-tuning the output schema. Functions, classes, and other exotic JS objects such instances of Promise, ArrayBuffer, and others will be explored in a future post.
Footnotes
This assumes all values that are not string, number, boolean, undefined, or null are objects, but there are arrays too... ↩