react-jsonpath-editor
react-jsonpath-editor copied to clipboard
Feature study : build JSON path from a click in JSON preview
Feature study : build JSON path from a click in JSON preview
Simple cases
[
"toto", //$.0
"tata" //$.1
]
{
"key1": "value1", //$.key1
"key2": "value2" //$.key2
}
Complex case
[
"toto",
"tata",
{
"key": "value",
"filter": 12
/**
* This is a leaf node with following properties
* {
type: "objectEntry",
childNodes: [],
key: 'filter',
value: 12,
parentNode: { // (1)
type: "arrayEntry",
childNodes: [
{
type: "objectEntry",
childNodes: [],
key: 'filter',
value: 12,
parentNode: (1)
},
{
type: "objectEntry",
childNodes: [],
key: "key",
value: "value",
parentNode: (1)
}
],
key: 2,
parentNode: {
type: "rootArray"
}
}
}
* - $[?(@.key === "value")].filter - Get "filter" value for array entry with "key" property equals to "value"
* - $[?(@.filter === 12)].filter - Get "filter" value for array entry with "filter" property equals to "12"
* - $[2].filter - Get "filter" value for second array entry
* - $[(@length - 1)].filter - Get "filter" value for second last array entry
* - $..filter - Get all "filter" values
?? - $[?(@.filter >= 10)].filter -
**/
},
{
"key": "value2",
"filter": 1
},
]
Even more complex case
{
"key": [
{
"key": "value",
"filter": 12,
"items": [
{
"key2": "value2", // Just at this level there is an explosion of possibilities
"filter": 12
}
]
}
]
}
Algo study
Its like a tree.
Each node can be an object or an array
$ <- root node
Listing all possibilities is too consuming, reverse the tree traversal sounds to be a better approach.
In input we got a tree leaf. From this leaf we can find its first ancestor node. Let's prototype
interface Node {
type: "rootObject" | "rootArray" | "objectEntry" | "arrayEntry";
childNodes: Node[];
key?: string | number;
value?: string | number | boolean;
parentNode?: Node; //Have to compute it while building datastructure
}
async buildJsonPathFrom(leafNode: Node, path: string = '') {
const ancestor = leafNode.parentNode;
if (ancestor.type === "arrayEntry") {
childNodes = ancestor.childNodes;
//Prompt user to choose with which node he want to filter with
const filteringNode = await diplayFilterByChoices(childNodes);
path = `[?(@.${filteringNode.key} === '${filteringNode.value}')].${leafNode.key}`;
} else if (ancestor.type === "objectEntry") {
path = `${ancestor.key}.${leafNode.key}`;
} else if (ancestor.type.startsWith("root")) {
path = `$.${leafNode.key}`;
return path;
}
return buildJsonPathFrom(ancestor.parentNode, path);
}