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月27日T11: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月27日T11: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"
}]
EugenSunic
13.8k15 gold badges68 silver badges97 bronze badges
asked Aug 28, 2020 at 9:10
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] ) );

answered Aug 28, 2020 at 9:25
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, ''))

answered Aug 28, 2020 at 9:49

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.