3

I have some attributes from a nested object that is inside the parent object but I would like to merge nested object with the parent object to be flatten.

Original object:

enrollment = {
  user: {
    id: 'string',
    name: 'string'
  },
  finished: 'boolean',
  path: 'string'
}

expected flatten object:

user: {
  id: 'string',
  name: 'string',
  finished: 'boolean',
  path: 'string'
}

6 Answers 6

4

You can recursively build object any number of nested objects. So, this function is not your case dependent:

var enrollment = {
user: {
    id: 'string',
    name: 'string'
},
finished: 'boolean',
path: 'boolean'
}

var enrollment2 = {
user: {
    id: 'string',
    name: 'string'
},
test: {
    test1: {
        test2: {
            val0:'val0',
            test4: { //3rd level nested object for example
                val1: 'val1',
                val2: 'val2'
            }
        }
    }
},
finished: 'boolean',
path: 'boolean'
}

const flat = (obj, out) => {
    Object.keys(obj).forEach(key => {
        if (typeof obj[key] == 'object') {
            out = flat(obj[key], out) //recursively call for nesteds
        } else {
            out[key] = obj[key] //direct assign for values
        }

    })
    return out
}

console.log(flat(enrollment, {}))
console.log(flat(enrollment2, {}))

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

1 Comment

In the general use case - in case of null value, typeof obj[key] return 'object' and TypeError exception will be thrown in the inner recursion.
4

I needed something that avoids rewriting keys with the same name that were in different levels in the original object. So I wrote the following:

const flattenObject = (obj, parentKey = '') => {
    if (parentKey !== '') parentKey += '.';
    let flattened = {};
    Object.keys(obj).forEach((key) => {
        if (typeof obj[key] === 'object' && obj[key] !== null) {
            Object.assign(flattened, flattenObject(obj[key], parentKey + key))
        } else {
            flattened[parentKey + key] = obj[key]
        }
    })
    return flattened;
}

var test = {
    foo: 'bar',
    some: 'thing',
    father: {
        son1: 'son1 value',
        son2: {
            grandchild: 'grandchild value',
            duplicatedKey: 'note this is also used in first level',
        },
    },
    duplicatedKey: 'note this is also used inside son2',
}

let flat = flattenObject(test);
console.log(flat);

// how to access the flattened keys:
let a = flat['father.son2.grandchild'];
console.log(a);

Also checks if the object is null, as I was having some problems with that in my usage.

Comments

1

Here's a quick and dirty way to flatten your object:

var enrollment = {
    user: {
        id: 'string',
        name: 'string',
    },
    fineshed: true,
    path: false,
};

var user = Object.assign(enrollment.user);
user.fineshed = enrollment.fineshed;
user.path = enrollment.path;

For a generic method with a couple of caveats of no shared key names and only flattening 1 level of depth:

var enrollment = {
	user: {
		id: 'string',
		name: 'string',
	},
	fineshed: true,
	path: false,
};

const flatten = (object) => {
	let value = {};
	for (var property in object) {
		if (typeof object[property] === 'object') {
			for (var p in object[property]) {
				value[p] = object[property][p];
			}
		} else {
			value[property] = object[property];
		}
	}

	return value;
};

let user = flatten(enrollment);

console.log(user);

Comments

1

using recursion and reduce.

note that if value itself is an array containing objects, you might want add another check like !Array.isArray(value) depending on your case

function flatObj(obj) {
  return Object.entries(obj).reduce(
    (flatted, [key, value]) =>
      typeof value == "object"
        ? { ...flatted, ...flatObj(value) }
        : { ...flatted, [key]: value },
    {}
  );
}

Comments

0

Just want a single Object:

const enrollment = {
  user: {
    id: 'string',
    name: 'string'
  },
  finished: 'boolean',
  path: 'boolean'
}
function propsToUser(enrollObj){
  const u = {...enrollObj.user};
  for(let i in enrollObj){
    if(i !== 'user')u[i] = enrollObj[i];
  }
  return u;
}
const user = propsToUser(enrollment);
console.log(user);

Comments

0

Below code snippet takes nested input object like this :

{
        name:'Namig',
        surname:'Hajiyev',
        address:{
            city:'Sumgait',
            country:'Azerbaijan',
            geo: {
                lat:'40.5897200',
                long:'49.6686100'
            }
        }
    }

and returns result flattened object like this:

{
  "name": "Namig",
  "surname": "Hajiyev",
  "address.city": "Sumgait",
  "address.country": "Azerbaijan",
  "address.geo.lat": "40.5897200",
  "address.geo.long": "49.6686100"
}

Here is my code :

function flattenObject(obj, newObj, prefix) {
    newObj = newObj || {};
    prefix = prefix || "";
    for (var key in obj) {
        if (obj.hasOwnProperty(key)) {
            const type = typeof obj[key];
            const newKey = !!prefix ? prefix + "." + key : key;
            if (type === "string") {
                newObj[newKey] = obj[key];
            }
            else if (type === "object") {
                flattenObject(obj[key], newObj, newKey);
            }
        }
    }
    return newObj;
}

var obj = {
    name:'Namig',
    surname:'Hajiyev',
    address:{
        city:'Sumgait',
        country:'Azerbaijan',
        geo: {
            lat:'40.5897200',
            long:'49.6686100'
        }
    }
}

console.log(flattenObject(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.