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

Your Answer

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.