Aschenauer
Aschenauer

Reputation: 57

How to get Path to JSON key:value pair

I have a huge (~20000 lines) .json file, which was converted from an .aml File (markup based on XML). I can find the key:value pair by key or value, but I can not find out where it is like "Document[0].Level[3][2].Sub[2]"

The goal is to convert the .json File into a different one, partly usable for JSON-LD and I need to summarize or move and declare some entries of the original .json

For example at following JSON:

myObj = {
"name": "John",
"age": 30,
"cars": {
    "garage1": [{
        "Car1": "Ford",
        "Car2": "Seat"
    }],
    "garage2": [{
        "car2": "BMW",
        "car3": "Fiat"
    }]
}
} 

I use following Code to find the pair:

function getKeys(obj, val) {
var objects = [];
for (var i in obj) {
    if (!obj.hasOwnProperty(i)) continue;
    if (typeof obj[i] == 'object') {
        objects = objects.concat(getKeys(obj[i], val));
    } else if (obj[i] == val) {
       // objects.push(i);
        objects.push(obj);
    }
}
   return objects;
}

And with

result = getKeys(myObj,'Ford'); 

I get:

[ { Car1: 'Ford', Car2: 'Seat' } ]

The Problem is, that I don't know where this is and also I can not have a look what is in the second garage if there is one.

I would like to receive also Path Information, like:

cars.garage1

With that information I could look trough the higher level, of for example of Cars

In this example I could just save the path in my second "if"-relation. But in my big file I would also need to delete some path notes if the algorithm goes too deep and would need to go in a higher level again to continue the search. At least that was my idea.

Is there any command or package to do so or do I need to save the route from searching for the key?

This is my first Post, I am also open to Hints how improve the way of asking Questions here :)

Upvotes: 3

Views: 2374

Answers (2)

Nina Scholz
Nina Scholz

Reputation: 386654

You could collect the nested keys and return an array of the found pathes.

function getPath(object, value) {
    return Object
        .keys(object)
        .reduce((r, k) => {
            var kk = Array.isArray(object) ? `[${k}]` : `${k}`;
            if (object[k] === value) {
                r.push(kk);
            }
            if (object[k] && typeof object[k] === 'object') {
                r.push(...getPath(object[k], value).map(p => kk + (p[0] === '[' ? '' : '.') + p));
            }
            return r;
        }, []);
}

var object = { name: "Ford", age: 30, cars: { garage1: [{ Car1: "Ford", Car2: "Seat" }], garage2: [{ car2: "BMW", car3: "Fiat" }] } };

console.log(getPath(object, 'Ford'));

Upvotes: 2

trincot
trincot

Reputation: 350310

To get the path, let your recursive function return an array, and prepend the key to it every time the recursive call is successful:

function getKeys(obj, val) {
    if (obj === val) return []; // Found it!
    if (Object(obj) !== obj) return; // A primitive value, but no match
    for (const key in obj) {
        if (!obj.hasOwnProperty(key)) continue;
        const result = getKeys(obj[key], val);
        if (result) return [key, ...result];
    }
}

const myObj = {"name": "John","age": 30,"cars": { "garage1": [{ "Car1": "Ford", "Car2": "Seat" }], "garage2": [{ "car2": "BMW","car3": "Fiat"}] }};
console.log(getKeys(myObj, "Ford").join("/"));

Upvotes: 1

Related Questions