react-jsonpath-editor icon indicating copy to clipboard operation
react-jsonpath-editor copied to clipboard

Feature study : build JSON path from a click in JSON preview

Open JeanBaptisteWATENBERG opened this issue 6 years ago • 0 comments

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);
}

JeanBaptisteWATENBERG avatar Mar 16 '19 12:03 JeanBaptisteWATENBERG