Following is an object with some deep properties.
const InitialObj = {
Store: {propsFromStore: {}},
Market: {propsFromMarket: {}},
GoDown: {prop
You can create a function to check if the key is one of "Store", "Market" or "GoDown" and replace it with the corresponding value. If the value of the key is an object(typeof object) then recursively call the function and repeat.
const obj = {
Store: {
propsFromStore: {}
},
Market: {
propsFromMarket: {}
},
GoDown: {
propsFromDown: {}
}
}
const whiteList = ["Store", "Market", "GoDown"]
const replacer = object => Object.fromEntries(Object
.entries(object)
.map(([key, value]) =>
[key, value && typeof value === "object" ? replacer(value) : whiteList.includes(value) ? obj[value] : value ]
)
)
var initialObj = {
fruits: {store_c: "Store", otherProp1: {store_e: "Store", otherSubProp1: {}}, otherProp2: {}},
vegetables: {market_d: "Market", otherProp1: {otherSubProp1: {godown_r: "GoDown", }}},
fancy:{store_t: "Store", market_d: "Market", otherProp1: {otherSubProp1: {godown_r: "GoDown", }}},
}
const finalObj = replacer(initialObj)
console.log(finalObj) // desired output
I hope it helps.
You can use a first function which will find which props should serve as references (Store, Market, GoDown), and use recursion on the others, with an auxiliary function:
const InitialObj = {
Store: {propsFromStore: {}},
Market: {propsFromMarket: {}},
GoDown: {propsFromDown: {}},
fruits: {store_c: "Store", otherProp1: {store_e: "Store", otherSubProp1: {}}, otherProp2: {}},
vegetables: {market_d: "Market", otherProp1: {otherSubProp1: {godown_r: "GoDown", }}},
fancy:{store_t: "Store", market_d: "Market", otherProp1: {otherSubProp1: {godown_r: "GoDown", }}},
};
function hydrateObj(obj, keys) {
const refs = keys.reduce((o, k) => ({...o, [k]: obj[k]}), {});
return Object.entries(obj).reduce((res, [k, v]) => {
if(!keys.includes(k)) {
res[k] = hydrateObjAux(v, keys, refs);
}
return res;
}, {});
}
function hydrateObjAux(obj, keys, refs) {
return Object.entries(obj).reduce((res, [k, v]) => {
if(keys.includes(v)) {
res[k] = refs[v];
} else {
res[k] = hydrateObjAux(v, keys, refs);
}
return res;
}, {});
}
const res = hydrateObj(InitialObj, ['Store', 'Market', 'GoDown']);
document.body.innerHTML = '<pre>' + JSON.stringify(res, 0, 4) + '</pre>';
Based on your comments that you separate replacement object from InitialObj by capitalised first letter.
any
for every type. It better to define and set correct type if you'r using ts.const InitialObj: any = {
Store: {propsFromStore: {}},
Market: {propsFromMarket: {}},
GoDown: {propsFromDown: {}},
fruits: {store_c: "Store", otherProp1: {store_e: "Store", otherSubProp1: {}}, otherProp2: {}},
vegetables: {market_d: "Market", otherProp1: {otherSubProp1: {godown_r: "GoDown", }}},
fancy:{store_t: "Store", market_d: "Market", otherProp1: {otherSubProp1: {godown_r: "GoDown", }}},
}
const replacementDict: any ={}
// take Store, Market, GoDown from InitialObj to replacementDict
Object.keys(InitialObj).forEach(key =>{
// Check if the first letter is capitalised or not
if(key[0].match(/^[A-Z]$/)){
replacementDict[key] = InitialObj[key]
delete InitialObj[key]
}
})
function converter(obj: any){
if(typeof obj !== "object") return
Object.entries(obj).forEach(([key, value]: [any, any]) => {
if(replacementDict[value]){
obj[key] = replacementDict[value]
}
if(typeof obj[key] === "object"){
converter(obj[key])
}
})
}
converter(InitialObj)
console.log(InitialObj)
The obvious solution would be to simply recursively iterate over all object properties, however it might be unnecessarily complicated and time consuming for such a simple case. Assuming we want to replace all instances of values being strings like "Store"
and so on, we could transform the object into a string and do a simple replace function on it's contents, turning it back into object afterwards.
const obj = {
Store: {propsFromStore: {}},
Market: {propsFromMarket: {}},
GoDown: {propsFromDown: {}},
fruits: {store_c: "Store", otherProp1: {store_e: "Store", otherSubProp1: {}}, otherProp2: {}},
vegetables: {market_d: "Market", otherProp1: {otherSubProp1: {godown_r: "GoDown", }}},
fancy:{store_t: "Store", market_d: "Market", otherProp1: {otherSubProp1: {godown_r: "GoDown" }}}
}
// please note the existence of ":" in front of the searched term which ensures the replaced value is actually a value not a key of the nested objects
const replaced = JSON.parse(JSON.stringify(obj)
.replace(/:"Store"/g, ": {\"propsFromStore\": {}}")
.replace(/:"Market"/g, ": {\"propsFromMarket\": {}}")
.replace(/:"GoDown"/g, ": {\"propsFromDown\": {}}"))
console.log(replaced)
Of course this solution would not work if the properties of your objects are more complicated / require their own custom serialization method. An example of such a situation:
const obj = { x: [10, undefined, null] }
console.log(JSON.stringify(obj)); // logs `{"x":[10,null,null]}` effectively losing distinction between undefined and null
const replaced = JSON.stringify(obj, (k, val) => typeof val === "undefined" ? "undefined" : val );
console.log(replaced) // with custom replacer can keep information that would otherwise be lost
const rereplaced = JSON.parse(replaced, (k, val) => val === "undefined" ? undefined : val)
console.log(rereplaced) // gets it's undefined value back