Javascript/JSON get path to given subnode?

后端 未结 4 1669
迷失自我
迷失自我 2020-12-03 17:29

How would you get a JSON path to a given child node of an object?

E.g.:

var data = {
    key1: {
        children: {
            key2:\'value\',
             


        
相关标签:
4条回答
  • 2020-12-03 18:02

    var data = {
      // Your data is here
      a: {
        b: {
          c: {
            d: "Assalamu alal muslimin"
          }
        }
      },
      // Your function is here
      take: function(path) {
        var temp = this; // take a copy of object
        if(!path) return temp; // if path is undefined or empty return the copy
        path = path.split("/");
        for(var p in path) {
          if(!path[p]) continue; // means "a/" = "a"
          temp = temp[path[p]]; // new data is subdata of data
          if(!temp) return temp; 
        }
        return temp;
      }
    };
    <input placeholder="Please enter the path"/>
    <button onclick="document.querySelector('div').innerText = JSON.stringify(data.take(document.querySelector('input').value))">
      Try it
    </button>
    <br><br>
    Data: {a:{b:{c:{d:"Assalamu alal muslimin"}}}}
    <br><br>
    Code: data.take(path)
    <br><br>
    Result:
    <div></div>

    Shortly the function is :

    function getDataByPath(data, path) {
        if(!path) return data; // if path is undefined or empty return data
        path = path.split("/");
        for(var p in path) {
            if(!path[p]) continue; // "a/" = "a"
          . data = data[path[p]]; // new data is subdata of data
            if(!data) return data; // "a/b/d" = undefined
        }
        return data;
    }
    

    And the shortest function but it may give errors if you entered wrong path:

    function getDataByPath(data, path) {
      for(var i in path.split("/")) data = data[path[i]];
      return data;
    }
    
    0 讨论(0)
  • 2020-12-03 18:05

    So you have a variable with the value "key3", and you want to know how to access this property dynamically, based on the value of this string?

    var str = "key3";
    data["key1"]["children"][str];
    

    EDIT

    Wow, I can't believe I got this on the first try. There might be some bugs in it, but it works for your test case

    LIVE DEMO

    var x = data.key1.children.key4;
    
    var path = "data";
    function search(path, obj, target) {
        for (var k in obj) {
            if (obj.hasOwnProperty(k))
                if (obj[k] === target)
                    return path + "['" + k + "']"
                else if (typeof obj[k] === "object") {
                    var result = search(path + "['" + k + "']", obj[k], target);
                    if (result)
                        return result;
                }
        }
        return false;
    }
    
    var path = search(path, data, x);
    console.log(path); //data['key1']['children']['key4']
    
    0 讨论(0)
  • 2020-12-03 18:17

    This is the way i have done this.

    /**
     * Converts a string path to a value that is existing in a json object.
     * 
     * @param {Object} jsonData Json data to use for searching the value.
     * @param {Object} path the path to use to find the value.
     * @returns {valueOfThePath|undefined}
     */
    function jsonPathToValue(jsonData, path) {
        if (!(jsonData instanceof Object) || typeof (path) === "undefined") {
            throw "Not valid argument:jsonData:" + jsonData + ", path:" + path;
        }
        path = path.replace(/\[(\w+)\]/g, '.$1'); // convert indexes to properties
        path = path.replace(/^\./, ''); // strip a leading dot
        var pathArray = path.split('.');
        for (var i = 0, n = pathArray.length; i < n; ++i) {
            var key = pathArray[i];
            if (key in jsonData) {
                if (jsonData[key] !== null) {
                    jsonData = jsonData[key];
                } else {
                    return null;
                }
            } else {
                return key;
            }
        }
        return jsonData;
    }  
    

    For testing,

    var obj = {d1:{d2:"a",d3:{d4:"b",d5:{d6:"c"}}}};
    jsonPathToValue(obj, "d1.d2"); // a 
    jsonPathToValue(obj, "d1.d3"); // {d4: "b", d5: Object}
    jsonPathToValue(obj, "d1.d3.d4"); // b
    jsonPathToValue(obj, "d1.d3.d5"); // {d6: "c"}
    jsonPathToValue(obj, "d1.d3.d5.d6"); // c
    

    Hope that will help someone.

    0 讨论(0)
  • 2020-12-03 18:18

    My solution:

    • depth first search based on a given reference
    • uses recursion
    • handles arrays

    (Result can be retrieved using this deep_value function.)

    var key4Ref = { abc: 123 }
    
    var data = {
        key1: {
            children: {
                key2:'value',
                key3:'value',
                key4: key4Ref
            }, 
            key5: 'value'
        }
    }
    
    // find the path to a 'ref' within an object 'data'.
    const pathTo = (ref, data, path = []) => {
      const found = data && Object.entries(data).find(([k,v]) => {
        if (v === ref) return path.push(k)
        if (typeof v === 'object') {
          const tmp = pathTo(ref, v, [...path, k])
          if (tmp) return path = tmp
        }
      })
      if (found) return path
    }
    
    console.log(pathTo(key4Ref, data).join('.'))

    0 讨论(0)
提交回复
热议问题