You could use this recursive, pure JavaScript function:
The snippet below applies this function to the example data you provided and returns the required result:
function extract(data, select, curpath) {
var result = {};
// Part of the path that has been traversed to get to data:
curpath = curpath || '';
if (typeof data !== 'object') { // data is a primitive (we assume)
return data;
}
if (typeof data.slice === 'function') { // data is an Array
return data.map(function (el, idx) {
return extract(el, select, curpath); // same path!
});
}
// data is an Object:
// The specific case of the "__metadata" property
if (data.__metadata !== undefined && curpath.length === 0) {
result.__metadata = data.__metadata;
}
// Core of this algorithm: take the relevant paths only...
var subselect = select.filter(function(path) {
return (path+"https://stackoverflow.com/").indexOf(curpath) == 0;
});
subselect.forEach(function (path, _, subselect) {
// then get the next property in such path...
var prop = path.substr(curpath.length).split("https://stackoverflow.com/")[0];
// and check if we have that property on the current object:
if (data[prop] !== undefined) {
// If so, recurse while adding this to the current path:
result[prop] = extract(data[prop], subselect, curpath+prop+"https://stackoverflow.com/");
}
});
// The specific case of the "results" property
if (data.results !== undefined) { // recurse with same path!
result.results = extract(data.results, select, curpath);
}
return result;
}
// Test data
var oDataSet = [{
__metadata: {
aaa: 111,
bbb: 222
},
to_ExcludedTerms: {results: []},
to_ListTypeGroupAssignment: {
results: [
{
AuthorisationGroup: 'AuthorisationGroup 1',
ListTypeGroup: 'ListTypeGroup1',
ListTypeGroupDescription: 'ListTypeGroupDescription 1',
ParentKey: '8ae25d47-c3cc-4ee3-a040-ea00505692111',
__metadata: {}
},
{
AuthorisationGroup: 'AuthorisationGroup 2',
ListTypeGroup: 'ListTypeGroup2',
ListTypeGroupDescription: 'ListTypeGroupDescription 2',
ParentKey: '34bcdc74-ab42-4538-8657-0a2b0473fcb7',
__metadata: {}
},
{
AuthorisationGroup: 'AuthorisationGroup 3',
ListTypeGroup: 'ListTypeGroup3',
ListTypeGroupDescription: 'ListTypeGroupDescription 3',
ParentKey: '34bcdc74-ab42-4538-8657-0a2b0473fcb5',
__metadata: {}
}
]
}
}, {
__metadata: {
aaa: 333,
bbb: 444
},
to_ExcludedTerms: {results: []},
to_ListTypeGroupAssignment: {
results: [
{
AuthorisationGroup: 'AuthorisationGroup 6',
ListTypeGroup: 'ListTypeGroup6',
ListTypeGroupDescription: 'ListTypeGroupDescription 6',
ParentKey: '8ae25d47-c3cc-4ee3-a040-ea00505692116',
__metadata: {}
},
{
AuthorisationGroup: 'AuthorisationGroup 7',
ListTypeGroup: 'ListTypeGroup7',
ListTypeGroupDescription: 'ListTypeGroupDescription 7',
ParentKey: '34bcdc74-ab42-4538-8657-0a2b0473fcb7',
__metadata: {}
},
{
AuthorisationGroup: 'AuthorisationGroup 8',
ListTypeGroup: 'ListTypeGroup8',
ListTypeGroupDescription: 'ListTypeGroupDescription 8',
ParentKey: '34bcdc74-ab42-4538-8657-0a2b0473fcb8',
__metadata: {}
}
]
}
}
];
var aProperties = [
"to_ListTypeGroupAssignment/ListTypeGroup",
"to_ListTypeGroupAssignment/ListTypeGroupDescription"
];
// (End of sample data)
// Call the function to get the result:
var aSelectedDataSet = extract(oDataSet, aProperties);
// For this snippet only: output the result in readable format
document.write('<pre>'+JSON.stringify(aSelectedDataSet, 0, 4)+'</pre>');
Explanation of the algorithm:
The code is commented. This is how the algorithm works:
- The function is recursive and takes the current data, which will be just a sub section of the original data once the function is called recursively.
- The function also takes the path-style properties to select. Also this list will be shorter as the function is called recursively, so it only has those entries that are still relevant to the data section.
- The third argument is the path that has already been traversed. At the initial call this is just the empty string, but as the recursion kicks in, it will become ‘to_ListTypeGroupAssignment/’, and later even ‘to_ListTypeGroupAssignment/ListTypeGroup/’ (always with terminating slash).
- Each call of the function will return a part of the given data that matches the (path-style) selection.
- The function starts by identifying the type of the data: whether it is a primitive value (a string, number, boolean), or an array (which is the case at the initial call), or an (non-array) object.
- If it is an array, the function is just called recursively for each element without adding anything to the path. The result of each call is then stored in an array, which becomes the return value.
- If it is a primitive value, it means we recursed to a “leaf” in the “tree”. And since we got here, we may assume the “path” was matching up until this point, and so the primitive value must be returned so it can be added to the result
- It it is an object, the select paths are traversed to see if the next level in those paths matches with an object property of the current data. If so, that property value is passed via a recursive call, while also adding that piece of the path to the “current” path
There are obviously the exceptions for __metadata
and results
, which are treated separately in the code.
1
solved How to match values between two objects and create new with specific values