Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
Alex A. Naanou 2026-01-17 14:43:29 +03:00
parent 6977c4fd5c
commit 7b994416cd
2 changed files with 74 additions and 1 deletions

View File

@ -188,8 +188,70 @@ Extensions to JSON:
### Structural paths ### Structural paths
Paths are used for internal references in cases when objects are
encountered multiple times, e.g. in recursion.
A path is an array of keys, the meaning of each key depends on the data
structure traversed:
- array -> number
- object -> string
- set -> number -- item order in set
- map -> pair of numbers -- the first indicates item order the second
if 0 selects the key, if 1 selects the value.
Note that string path items are unambiguous and are always treated as
attributes.
For examples see next section.
### Recursion and internal linking ### Recursion and internal linking
If an object is encountered for a second time it will be serialized as
a reference by path to the first occurrence.
An empty path indicates the root object.
Format:
```bnf
<ref> ::=
'<REF' <path> '>'
<path> ::=
'[' <path-items> ']'
<path-items> ::=
<item>
| <item> ',' <path-items>
<item> ::=
<number>
| <string>
```
Example:
'''javascript
var o = []
o.o = o
// root object reference...
serialize(o) // -> '[<REF[]>]'
// array item...
serialize([o]) // -> '[[<REF[0]>]]'
// set item...
// NOTE: the path here is the same as in the above example -- since we
// use ordered topology for paths sets do not differ from arrays.
serialize(new Set([o])) // -> 'Set([[<REF[0]>]])'
// map key...
serialize(new Map([[o, 'value']])) // -> 'Map([[[<REF[0,0]>],"value"]])'
// map value...
serialize(new Map([['key', o]])) // -> 'Map([["key",[<REF[0,1]>]]])'
'''
### null types ### null types

View File

@ -380,8 +380,13 @@ module.eJSON = {
&& i == path.length-1){ && i == path.length-1){
return [path.slice(0, -1), obj] } return [path.slice(0, -1), obj] }
obj = obj instanceof Set ? obj =
// special case: string key -> attribute...
typeof(k) == 'string' ?
obj[k]
: obj instanceof Set ?
[...obj][k] [...obj][k]
// takes two items off the path -- [intex, key/value]...
: obj instanceof Map ? : obj instanceof Map ?
[...obj][k][path[++i]] [...obj][k][path[++i]]
: obj[k] } : obj[k] }
@ -405,6 +410,12 @@ module.eJSON = {
setItem: function(obj, path, value){ setItem: function(obj, path, value){
var [p, parent] = this._getItem(obj, path.slice(0, -1)) var [p, parent] = this._getItem(obj, path.slice(0, -1))
var k = path.at(-1) var k = path.at(-1)
// special case: string kye -> attr...
if(typeof(k) == 'string'){
parent[k] = value
return value }
if(parent instanceof Set){ if(parent instanceof Set){
var elems = [...parent] var elems = [...parent]
elems[k] = value elems[k] = value