I have the below object inputObj
and I want to convert it to a simple object like outputObj
.
var inputObj = {
'a' : 1,
'b' : true,
'c' : 'string1',
'd' : {
'e' : 'string2',
'f' : false,
'g' : 5,
'h' : {
'i' : 7,
'j' : 'string3',
'k' : [
{
'name' : 'l',
'value': 11
},
{
'name' : 'm',
'value': {
'n' : 13,
'o' : 'string4'
}
}
]
}
},
'p' : [
{
'name' : 'q',
'value': 15
},
{
'name' : 'r',
'value': 'Awesome!'
}
]
}
var outputObj = {
'a' : 1,
'b' : true,
'c' : 'string1',
'e' : 'string2',
'f' : false,
'g' : 5,
'i' : 7,
'j' : 'string3',
'l' : 11,
'n' : 13,
'o' : 'string4',
'q' : 15,
'r' : 'Awesome!'
}
Please note that in case of array
the final output object would be build from name
and value
properties as per above example.
I have tried to implement the same using below code. I know as I am calling the nested function, the final object is getting reset and the scope is also different there. May be basic closure concept can solve this but I am confused with this. If you can correct my code or altogether new code is also fine.
function convertToFirstLevelObject( object ) {
var returnObj = {};
if( IsPrimaryDataType( object )) {
return object;
}
else {
if( object instanceof Array ) {
for ( var i = 0; i < object.length; i++ ) {
if( typeof object[i] === 'object' && !(object[i] instanceof Array) ) {
var key = object[i]['name'],
value = object[i]['value'];
if( IsPrimaryDataType( value )) {
returnObj[ key ] = value;
}
else {
convertToFirstLevelObject( value );
}
}
else{
/* This condition is for Array of Array */
if( object[i] instanceof Array ) {
convertToFirstLevelObject( object[i] );
} else {
console.log('Wrong data passed, expected data id object or Array of objects');
return;
}
}
}
}
else {
for ( var attr in object ) {
if ( object.hasOwnProperty( attr ) ) {
if( IsPrimaryDataType( object[ attr ] )) {
returnObj[ attr ] = object[ attr ];
}
else {
convertToFirstLevelObject( object[ attr ] )
}
}
}
}
}
return returnObj;
}
function IsPrimaryDataType( input ) {
var returnFlag = false;
if( input === null || input === 'undefined' || typeof input !== 'object' ) {
returnFlag = true;
}
return returnFlag;
}
I have the below object inputObj
and I want to convert it to a simple object like outputObj
.
var inputObj = {
'a' : 1,
'b' : true,
'c' : 'string1',
'd' : {
'e' : 'string2',
'f' : false,
'g' : 5,
'h' : {
'i' : 7,
'j' : 'string3',
'k' : [
{
'name' : 'l',
'value': 11
},
{
'name' : 'm',
'value': {
'n' : 13,
'o' : 'string4'
}
}
]
}
},
'p' : [
{
'name' : 'q',
'value': 15
},
{
'name' : 'r',
'value': 'Awesome!'
}
]
}
var outputObj = {
'a' : 1,
'b' : true,
'c' : 'string1',
'e' : 'string2',
'f' : false,
'g' : 5,
'i' : 7,
'j' : 'string3',
'l' : 11,
'n' : 13,
'o' : 'string4',
'q' : 15,
'r' : 'Awesome!'
}
Please note that in case of array
the final output object would be build from name
and value
properties as per above example.
I have tried to implement the same using below code. I know as I am calling the nested function, the final object is getting reset and the scope is also different there. May be basic closure concept can solve this but I am confused with this. If you can correct my code or altogether new code is also fine.
function convertToFirstLevelObject( object ) {
var returnObj = {};
if( IsPrimaryDataType( object )) {
return object;
}
else {
if( object instanceof Array ) {
for ( var i = 0; i < object.length; i++ ) {
if( typeof object[i] === 'object' && !(object[i] instanceof Array) ) {
var key = object[i]['name'],
value = object[i]['value'];
if( IsPrimaryDataType( value )) {
returnObj[ key ] = value;
}
else {
convertToFirstLevelObject( value );
}
}
else{
/* This condition is for Array of Array */
if( object[i] instanceof Array ) {
convertToFirstLevelObject( object[i] );
} else {
console.log('Wrong data passed, expected data id object or Array of objects');
return;
}
}
}
}
else {
for ( var attr in object ) {
if ( object.hasOwnProperty( attr ) ) {
if( IsPrimaryDataType( object[ attr ] )) {
returnObj[ attr ] = object[ attr ];
}
else {
convertToFirstLevelObject( object[ attr ] )
}
}
}
}
}
return returnObj;
}
function IsPrimaryDataType( input ) {
var returnFlag = false;
if( input === null || input === 'undefined' || typeof input !== 'object' ) {
returnFlag = true;
}
return returnFlag;
}
Edit:
Here is another inputObj
just to show that nesting can be of any level, here I have increased the level of array nesting. In any level of array nesting it will just look for if there is any object which has name
and value
both the property then it will flatten that.
var inputObj = {
'a' : 1,
'b' : true,
'c' : 'string1',
'd' : {
'e' : 'string2',
'f' : false,
'g' : 5,
'h' : {
'i' : 7,
'j' : 'string3',
'k' : [
{
'name' : 'l',
'value': 11
},
{
'name' : 'm',
'value': [{'n' : 13},{'o' : 'string4'}]
}
]
}
},
'p' : [
{
'name' : 'q',
'value': 15
},
{
'name' : 'r',
'value': 'Awesome!'
}
],
's' : [
[{
'name' : 't',
'value': 17
},
{
'name' : 'u',
'value': 'string5'
}],
[ 1, 2, 3],
[ "string6", "string7", "string8"],
[
[1,3,5],
[{'name' : 'v', 'value' : 19, 'anyOtherProp' : false}],
[2,4,6],
[{'name' : 'w', 'otherProp' : 31}]
]
]
}
OutObj should be like below
var outputObj = {
'a' : 1,
'b' : true,
'c' : 'string1',
'e' : 'string2',
'f' : false,
'g' : 5,
'i' : 7,
'j' : 'string3',
'l' : 11,
'n' : 13,
'o' : 'string4',
'q' : 15,
'r' : 'Awesome!',
't' : 17,
'u' : 'string5',
'v' : 19
}
JSON
– Rayon
Commented
Sep 9, 2016 at 11:53
outputObj
. Anyway, in what way does your code fail? Have you tried walking through the code in the debugger?
– user663031
Commented
Sep 9, 2016 at 12:08
You could use an iterative and recursive approach for looping the object.
function flatObject(source, target) {
Object.keys(source).forEach(k => {
if (Array.isArray(source[k])) {
source[k].forEach(function iter(a) {
if (Array.isArray(a)) {
a.forEach(iter);
return;
}
if (a !== null && typeof a === 'object') {
if ('name' in a || 'value' in a) {
'name' in a && 'value' in a && flatObject({ [a.name]: a.value }, target);
return;
}
flatObject(a, target);
}
});
return;
}
if (source[k] !== null && typeof source[k] === 'object') {
flatObject(source[k], target);
return;
}
target[k] = source[k];
});
}
var inputObj = { 'a': 1, 'b': true, 'c': 'string1', 'd': { 'e': 'string2', 'f': false, 'g': 5, 'h': { 'i': 7, 'j': 'string3', 'k': [{ 'name': 'l', 'value': 11 }, { 'name': 'm', 'value': [{ 'n': 13 }, { 'o': 'string4' }] }] } }, 'p': [{ 'name': 'q', 'value': 15 }, { 'name': 'r', 'value': 'Awesome!' }], 's': [[{ 'name': 't', 'value': 17 }, { 'name': 'u', 'value': 'string5' }], [1, 2, 3], ["string6", "string7", "string8"], [[1, 3, 5], [{ 'name': 'v', 'value': 19, 'anyOtherProp': false }], [2, 4, 6], [{ 'name': 'w', 'otherProp': 31 }]]] },
target = {};
flatObject(inputObj, target);
console.log(target);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Another approach. Very clear in my opinion. It relies heavily on recursion.
function convert(obj, mem) {
if (typeof obj != 'object' || obj === null) { // return primitive values and null directly
return obj
}
else if (obj.hasOwnProperty("name")) { // convert {name,value} objects to regular ones and recurse
if (!obj.value) return // value is required - if not available bail out
var o = {}
o[obj.name] = obj.value
return convert(o, mem)
}
else if (Array.isArray(obj)) { // iterate over array items and recurse
obj.forEach(function (item) {
convert(item, mem)
})
}
else {
for (var key in obj) { // iterate object items
var value = obj[key]
if (typeof value === "object") { // convert nested objects, dispose key
convert(value, mem)
}
else {
mem[key] = value // keep everything else
}
}
}
return mem // return result
}