Join(';') on nested object

Viewed 533

I'm trying to join all values from an object to semi colon separation, it works fine if the object is just one level:

obj = { 
    name: "one"
    additionalInfo: "hello"
    ...
};

Object.values(obj).join(';')

Result: one;hello

But if the object is nested:

obj = { 
    name: "one"
    additionalInfo: {
         description: "hello",
         ...
    }
};

Object.values(obj).join(';')

Result: one;[object Object]

The rest of the values except name is of course [object Object]. How can I join the level 2 values also?

The result I want is:

one;hello
8 Answers

You can use recursive function and loop through all the property like the following way:

var obj = { 
    name: "one",
    additionalInfo: {
         description: "hello",
    }
};
var val = [];
function getValue(obj){
  for (var property in obj) {
    if (obj.hasOwnProperty(property)) {
      if (typeof obj[property] == "object") {
        getValue(obj[property]);
      } else {
        val.push(obj[property]);          
      }
    }
  }
  return val.join(';');
}
var r = getValue(obj);

console.log(r)

You can take a recursive approach by making sure to convert any nested objects before joining the values of the entire level of the object:

function joinObjectValues(obj, delimiter = ";") {
  return Object.values(obj)
    .map(val => {
      //convert any objects recursively
      if (typeof val === "object") {
        return joinObjectValues(val, delimiter);
      }

      return val;
    })
    .join(delimiter)
}

let objOneLevel = {
  name: "one"
};

let objTwoLevels = {
  name: "one",
  additionalInfo: {
    description: "hello",
  }
};

let objThreeLevels = {
  name: "one",
  additionalInfo: {
    description: "hello",
    other: {
      customField: "world"
    }
  }
};


console.log(joinObjectValues(objOneLevel))
console.log(joinObjectValues(objTwoLevels))
console.log(joinObjectValues(objThreeLevels))

for more then one level you can do this :

var obj = { 
    name: "one",
    additionalInfo: {
         description: "hello",
         yes : 'world'
    }
};

function join(obj) {
  var arr = [];
  for(let key in obj) {
       typeof obj[key] == 'object'? arr.push(Object.values(obj[key])):arr.push(obj[key])
  }
  return arr.join(';')
}


console.log(join(obj))

To achieve expected result, use below option of changing object to string and find the values using : and }

  1. Change obj to string using JSON.stringify and split by ":"
  2. Getting words between ":" and "," and closing words between ":" and "}"
  3. Removing unwanted characters using repalce

working code sample and added few more objects for testing

obj = { 
    name: "one",
    additionalInfo: {
         description: "hello",
    },
    test: "abc",
    grandparent: {
      parent: {
        child: "child"
      }
    }
};

function concatObj(obj){
  let str = JSON.stringify(obj).split(":");
  return str.map(v => v.substr(0, v.indexOf(",")) || v.substr(0, v.indexOf("}"))).filter(Boolean).join(":").replace(/"|}|{/g,'')  
}

console.log(concatObj(obj))

codepen - https://codepen.io/nagasai/pen/pXpwdM?editors=1010

const obj = { 
  name: 'one',
  additionalInfo: {
    description: 'hello',
    sacri: ['m', 'e', 'n', 't', 'o'],
    foo: {
      bar: 'bat',
      biz: {
        tik: 'tock',
        hello: {
          world: 'YO',
          number: 5,
          bools: {
           positive: true,
            negative: false,
            funcs: {
             do: () => console.log('hello')
            }
          }
        }
      }
    }
  }
}

const stripObj = obj => (
  Object.values(obj)
  .reduce((prev, curr) => typeof curr === 'object' ? [...prev, stripObj(curr)] : [...prev, curr], [])
  .join(';')
)

const res = stripObj(obj)

console.log(res);

// nested objects are made flat to one level
var flattenObject = Object.assign(
  {}, 
  ...function _flatten(o) { 
    return [].concat(...Object.keys(o)
      .map(k => 
        typeof o[k] === 'object' ?
          _flatten(o[k]) : 
          ({[k]: o[k]})
      )
    );
  }(obj)
)

// now join the values
var joinedValues = Object.values(flattenObject).join(';');

console.log(joinedValues);

Doing it with a recursive function?

const obj = {
  name: "one",
  additionalInfo: {
    description: "hello",
  }
};


const mapped = flatObject(obj).flat().join(';')

console.log(mapped)


// this is a recursive function
function flatObject(obj) {
  const ret = []
  for (let val in Object.values(obj)) {
    if (typeof Object.values(obj)[val] !== 'string') {
      ret.push(flatObject(Object.values(obj)[val]))
    } else {
      ret.push(Object.values(obj)[val])
    }
  }
  return ret
}

Using recursion -

let objValues = [];
    function getObjValues(obj) {
        const objValuesArray = Object.values(obj);
        objValuesArray.forEach((objVal) => {
            if(typeof objVal === 'object') {
                getObjValues(objVal);
            } else {
                 objValues.push(objVal);
            }
        });
      return objValues.join(';');
    }

  const obj = {
            name: "one",
            additionalInfo: "hello",
            newObject: {
                newname: "two",
                info: "news"
            }
        }; 

const concatenatedValues = getObjValues(obj);
console.log(concatenatedValues);
Related