Reputation: 57
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
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
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