Search code examples
javascriptjsonjsonpath

Calculating the JSONPath


Assuming I have a fairly complex JSON object such as the one below:

{
  "firstName": "John",
  "address": [{
    "streetAddress": "1 street",
    "special": {
      "1 a": "1 b"
    }
  }, {
    "streetAddress": "2 naist street",
    "special": {
      "2 a": "2 b"
    }
  }],
  "phoneNumbers": [{
    "type": "iPhone",
    "number": "0123-4567-8888"
  }]
}

Are there any tools/libraries to calculate the JSONPath to a particular key/value pair?

For example: the JSONPath to the third row of data (streetAddress": "1 street") can be extracted using the JSONPath $.address[0].streetAddress.

Ideally I want something like this: calculateJSONPath(3) - where 3 is the 3rd key starting from the top and this function will return $.address[0].streetAddress. I don't imagine there'll be something that does exactly this, but I got to start somewhere, if not from scratch.

Edit: Sample use case: User loads a JSON file into my application. I allow them to select specific keys using my interface. Imagine checkboxes next to each key. Next the user can upload a second JSON file and see if the previously selected keys/values are present in the second JSON.

Edit 2: Searching won't work as I want the key/values selected by the user to be located in the same hierarchy as the first JSON. Eg: If the user selects "1 a": "1 b" in the first JSON file, the second JSON file must have the same key/value in the same nested hierarchy.


Solution

  • Here is a taste of what I said (check an checkbox to see my point):

    var $ = {
      "firstName": "John",
      "address": [{
        "streetAddress": "1 street",
        "special": {
          "2 a": "2 a"
        }
      }, {
        "streetAddress": "2 naist street",
        "special": {
          "2 a": "2 a"
        }
      }],
      "phoneNumbers": [{
        "type": "iPhone",
        "number": "0123-4567-8888"
      }]
    };
    
    
    // the recursive function that create the structure
    function createStructure(container, obj, path) {
      for(var key in obj) {
        var d = cd(key, path);
        if(typeof obj[key] == "object")
          createStructure(d, obj[key], path + "['" + key + "']");
        container.appendChild(d);
      }
    }
    
    // of course we call the function ...
    createStructure(document.getElementById("preview"), $, "$");
    
    
    // create a preview element (unimportant)
    function cd(prop, path) {
      var d = document.createElement("div");
      var s = document.createElement("span");
    
      var i = document.createElement("input");
      i.setAttribute("data-path", path + "['" + prop +"']");
      i.onclick = check;
      i.type = "checkbox";
      s.appendChild(i);
     
      s.appendChild(document.createTextNode(prop));
      d.appendChild(s);
      return d;
    }
    
    // the event handler (unimportant)
    function check(e) {
      if(e.target.checked)
        alert(e.target.getAttribute("data-path"));
    }
    div {
      padding: 5px;
      padding-left: 25px;
    }
    
    span {
      border-bottom: 1px solid black;
      border-left: 1px solid black;
    }
    <div id="preview">
      <span><input type="checkbox" data-path="$"/>$</span>
    </div>