Initial commit
This commit is contained in:
143
json.js
Normal file
143
json.js
Normal file
@@ -0,0 +1,143 @@
|
||||
|
||||
|
||||
|
||||
function jsonQuery(json, path, defaultValue = null) {
|
||||
|
||||
let toks = tokenizePath(path);
|
||||
let ptr = json;
|
||||
let search = null;
|
||||
let searchTok = null;
|
||||
let multiResult = null;
|
||||
|
||||
let tok;
|
||||
while (tok = toks.shift()) {
|
||||
switch (tok) {
|
||||
case ".": // find key
|
||||
search = 'key';
|
||||
break;
|
||||
case "[": // find array index
|
||||
search = "array";
|
||||
break;
|
||||
case "]": // find
|
||||
// if searchTok is "", match all items
|
||||
if (search !== "array") {
|
||||
throw new Error("Invalid path");
|
||||
}
|
||||
if (searchTok === null) {
|
||||
if (multiResult !== null) {
|
||||
throw new Error("Can't match full arrays on multiple levels");
|
||||
}
|
||||
multiResult = [];
|
||||
ptr.forEach(item => {
|
||||
let res = jsonQuery(item, toks.join(""));
|
||||
multiResult.push(res);
|
||||
});
|
||||
return multiResult;
|
||||
}
|
||||
if (typeof ptr[searchTok] === 'undefined') {
|
||||
return defaultValue;
|
||||
}
|
||||
ptr = ptr[searchTok];
|
||||
break;
|
||||
default:
|
||||
if (search === 'key') {
|
||||
// find key tok in ptr
|
||||
if (typeof ptr[tok] === 'undefined') {
|
||||
return defaultValue;
|
||||
} else {
|
||||
ptr = ptr[tok];
|
||||
}
|
||||
} else if (search === 'array') {
|
||||
// find index tok in ptr after finding a ]
|
||||
searchTok = tok;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
function jsonPatch(json, path, value) {
|
||||
let toks = tokenizePath(path);
|
||||
json = structuredClone(json);
|
||||
let ptr = json;
|
||||
let search = null;
|
||||
let searchTok = null;
|
||||
let multiResult = null;
|
||||
|
||||
let tok;
|
||||
while (tok = toks.shift()) {
|
||||
switch (tok) {
|
||||
case ".": // find key
|
||||
search = 'key';
|
||||
break;
|
||||
case "[": // find array index
|
||||
search = "array";
|
||||
break;
|
||||
case "]": // find
|
||||
// if searchTok is "", match all items
|
||||
if (search !== "array") {
|
||||
throw new Error("Invalid path");
|
||||
}
|
||||
if (searchTok === null) {
|
||||
throw new Error("Can't patch arrays yet");
|
||||
}
|
||||
if (typeof ptr[searchTok] === 'undefined') {
|
||||
return json;
|
||||
}
|
||||
ptr = ptr[searchTok];
|
||||
break;
|
||||
default:
|
||||
if (search === 'key') {
|
||||
// find key tok in ptr
|
||||
if (typeof ptr[tok] === 'undefined') {
|
||||
return defaultValue;
|
||||
} else {
|
||||
if (toks.length === 0) {
|
||||
ptr[tok] = value;
|
||||
return json;
|
||||
} else {
|
||||
ptr = ptr[tok];
|
||||
}
|
||||
}
|
||||
} else if (search === 'array') {
|
||||
// find index tok in ptr after finding a ]
|
||||
searchTok = tok;
|
||||
}
|
||||
}
|
||||
}
|
||||
// ptr = value;
|
||||
|
||||
return json;
|
||||
}
|
||||
|
||||
function tokenizePath(path) {
|
||||
let t = [];
|
||||
let b = null;
|
||||
for (let p = 0; p < path.length; p++) {
|
||||
let c = path[p];
|
||||
if (c == ".") {
|
||||
if (b !== null) t.push(b);
|
||||
b = null;
|
||||
t.push(".");
|
||||
} else if (c == "[") {
|
||||
if (b !== null) t.push(b);
|
||||
b = null;
|
||||
t.push("[");
|
||||
} else if (c == "]") {
|
||||
if (b !== null) t.push(b);
|
||||
b = null;
|
||||
t.push("]");
|
||||
} else {
|
||||
b = ((b===null)?"":b) + c;
|
||||
}
|
||||
}
|
||||
if (b !== null) t.push(b);
|
||||
return t;
|
||||
}
|
||||
|
||||
|
||||
export {
|
||||
tokenizePath,
|
||||
jsonQuery,
|
||||
jsonPatch,
|
||||
};
|
||||
Reference in New Issue
Block a user