2

I want to transform the nested JSON structure into a single object, with the dynamic key I tried with below code but it's work only with one level, I need to write some recursive function, that I am struggling to write the code for n level of nested JSON. Please advise.

 data.map((e) => { for (let key in e) { if (typeof e[key] === "object") { for (let onLevel in e[key]) { e[key + "." + onLevel] = e[key][onLevel]; } } } }); 

Example

Input JSON

[{ "Id": "0hb3L00000000jkQAA", "Name": "P-2797", "ContactEncounterId": "0ha3L000000001qQAA", "StartTime": "2020-06-27T11:00:00.000Z", "EncounterDuration": 25, "ContactEncounter": { "Name": "Grocery Shopping 17", "LocationId": "1313L0000004ENlQAM", "Id": "0ha3L000000001qQAA", "Location": { "Name": "Waitrose", "LocationType": "Site", "Id": "1313L0000004ENlQAM" } } }] 

OutPut JSON

[{ "Id": "0hb3L00000000jkQAA", "Name": "P-2797", "ContactEncounterId": "0ha3L000000001qQAA", "StartTime": "2020-06-27T11:00:00.000Z", "EncounterDuration": 25, "ContactEncounter.Name": "Grocery Shopping 17", "ContactEncounter.LocationId": "1313L0000004ENlQAM", "ContactEncounter.Id": "0ha3L000000001qQAA", "ContactEncounter.Location.Name": "Waitrose", "ContactEncounter.Location.LocationType": "Site", "ContactEncounter.Location.Id": "1313L0000004ENlQAM" }] 
1

2 Answers 2

3

As you said, you need to create a recursion to get deeper into the object. Which means, you would have to track the path where you are.

You could solve it in the following way

const input = [{ "Id": "0hb3L00000000jkQAA", "Name": "P-2797", "ContactEncounterId": "0ha3L000000001qQAA", "StartTime": "2020-06-27T11:00:00.000Z", "EncounterDuration": 25, "ContactEncounter": { "Name": "Grocery Shopping 17", "LocationId": "1313L0000004ENlQAM", "Id": "0ha3L000000001qQAA", "Location": { "Name": "Waitrose", "LocationType": "Site", "Id": "1313L0000004ENlQAM" } } } ]; function merge( source, target = {}, ...parents) { for (let [key, value] of Object.entries( source ) ) { const path = (parents || []).concat( key ); if (typeof value === 'object') { merge( value, target, ...path ); continue; } target[path.join('.')] = value; } return target; } console.log( merge( input[0] ) );

Or in the following way, where you just use Object.assign to assign the results of the deeper search into your current object.

const input = [{ "Id": "0hb3L00000000jkQAA", "Name": "P-2797", "ContactEncounterId": "0ha3L000000001qQAA", "StartTime": "2020-06-27T11:00:00.000Z", "EncounterDuration": 25, "ContactEncounter": { "Name": "Grocery Shopping 17", "LocationId": "1313L0000004ENlQAM", "Id": "0ha3L000000001qQAA", "Location": { "Name": "Waitrose", "LocationType": "Site", "Id": "1313L0000004ENlQAM" } } } ]; function merge( source, ...parents) { const mergedValue = {}; for (let [key, value] of Object.entries( source ) ) { const path = (parents || []).concat( key ); if (typeof value === 'object') { Object.assign( mergedValue, merge( value, ...path ) ); continue; } mergedValue[path.join('.')] = value; } return mergedValue; } console.log( merge( input[0] ) );

Sign up to request clarification or add additional context in comments.

3 Comments

This works well thanks unless there is null values eg if LocationType: null. Do you have any thoughts on how to handle this with Object.entries?
@ak85 well you could check if (value === null || value === undefined) { continue; } and probably ensure that source ain't null or undefined either?
You saved me like 2 hours of work on a Friday afternoon!
-1

Here is another approach by using the second parameter and passing the key when finding a nth level object.

const obj = { "Id": "0hb3L00000000jkQAA", "Name": "P-2797", "ContactEncounterId": "0ha3L000000001qQAA", "StartTime": "2020-06-27T11:00:00.000Z", "EncounterDuration": 25, "ContactEncounter": { "Name": "Grocery Shopping 17", "LocationId": "1313L0000004ENlQAM", "Id": "0ha3L000000001qQAA", "Location": { "Name": "Waitrose", "LocationType": "Site", "Id": "1313L0000004ENlQAM" } } } function flattenObj(obj, param) { let newObj = {}; for (let key in obj) { if (typeof obj[key] === 'object') { newObj = { ...newObj, ...flattenObj(obj[key], key + '.') } } else { newObj[param + key] = obj[key] } } return newObj; } console.log(flattenObj(obj, ''))

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.