Jim Dover
Jim Dover

Reputation: 623

Extracting nested values in a Javascript object

I have the following object:

var result = [{
"id": 89304,
"employeeDetails": {
    "id": 102524,
    "version": 9
}
}];

This is a snippet from a larger object that I'm trying to push into a MySQL table. What I'm trying to achieve is extract just the values into their own array, which would return this:

[ '89304', '102524', '9' ]

This way, I can easily push the values to the DB.

I have tried doing the following which works fine without nesting:

obKeys = Object.keys(result); console.log(obKeys);

However, with the nesting, the result I am getting is the following:

[ '0' ]

Can anyone let me know where I am going wrong, or suggest an alternative (better) way of doing this?

Thanks.

Upvotes: 1

Views: 2651

Answers (11)

niio
niio

Reputation: 346

use destructuring:

var result = [{
"id": 89304,
"employeeDetails": {
    "id": 102524,
    "version": 9
}
}];

const[{id, employeeDetails:{id: asEmplId}, employeeDetails:{version}}] = result.map(data => data);
console.log(id, asEmplId, version) //89304 102524 9

Upvotes: 2

emre-ozgun
emre-ozgun

Reputation: 762

//unpacks everything... (dynamic, data may change)
const log = console.log;
//can JSON.parse() and then use it. this is pure JS

const YOUR_DATA = [
    {
        id: 416,
        fullName: { firstName: 'Darth', lastName: 'Vader' },
        location: {
            street: 'Nowhere',
            postCode: { 1: '412' },
            skills: ['1', '2', { land: 'true' }],
        },
    },
];

const extractNestedValues = (data, extractedValues = []) => {
    data.forEach((obj) => {
        Object.values(obj).forEach((item) => {
            if (typeof item !== 'object') {
                extractedValues.push(item);
            } else {
                return extractNestedValues([item], extractedValues);
            }
        });
    });

    return extractedValues;
};

log(extractNestedValues(YOUR_DATA));
//[416,'Darth','Vader', 'Nowhere','412','1','2','true']

]

Upvotes: 1

Rohìt Jíndal
Rohìt Jíndal

Reputation: 27202

Some observations :

  • You are getting ['0'] because you are calling Object.keys() on an array instead of an object.
  • Object.keys() will return keys not the values.
  • As Robby said that the order of an object's properties is not guaranteed in JavaScript, so neither will be the order of your resulting array

DEMO

  • Using Array map() method.

var result = [{
"id": 89304,
"employeeDetails": {
    "id": 102524,
    "version": 9
}
}];

var arr = [];
result.map(function(item) {
    arr.push(item.id, item.employeeDetails.id, item.employeeDetails.version);
});

console.log(arr);

var result = [{
"id": 89304,
"employeeDetails": {
    "id": 102524,
    "version": 9
}
}];

var arr = [];
for (var i in result) {
  arr.push(result[i].id, result[i].employeeDetails.id, result[i].employeeDetails.version);
}

console.log(arr);

Upvotes: 1

vol7ron
vol7ron

Reputation: 42109

Retrieving Values by < Key/Type >

Setup

  • One helper function:

    1. .flatten(), flattens the array from multi-dimensions to only one
  • Two different method of retrieving values:

    1. .search(), retrieves all values that match a certain key

    2. .scalars(), retrieve all scalar values

Note: It's generally a bad idea to prototype the built-in objects. It is done in the following for distinction (array vs object association) as well as for readability and simplicity, but heed this warning.

Example

(function() {
  "use strict";

  // Makes multi-dimensional array, one-dimensional
  Array.prototype.flatten = function() {
    return this.reduce((acc, val) => {
      return acc.concat(
        Array.isArray(val) ? val.flatten() : val
      )
    }, []);
  };

  // Iterate over keys and values
  // Return value that matches search_key if not an object
  Object.prototype.search = function(search_key) {
    var obj = this;

    var vals = Object.keys(obj).map(key => {
      if (typeof obj[key] === 'object' && obj[key] !== null)
        return obj[key].search(search_key);
      else if (search_key === key)
        return obj[key];
    });
    return vals.filter(val => (val !== undefined));
  };

  // Iterate over keys and values
  // Return scalars
  Object.prototype.scalars = function() {
    var obj = this;

    var vals = Object.keys(obj).reduce((acc, key) => {
      if (typeof obj[key] !== 'object')
        acc[acc.length] = obj[key];
      else if (obj[key] !== null)
        acc[acc.length] = obj[key].scalars();
      return acc;
    }, []);
    return vals.filter(val => (val !== undefined));
  };


  // Dataset
  var result = [{
    "id": 89304,
    "employeeDetails": {
      "id": 102524,
      "version": 9
    }
  }];


  // Test 1: values of a key
  console.log(
    "obj.search('id'):",
    result.map(obj => {
      return obj.search('id')
    }).flatten()
  );

  // Test 2: all scalar values
  console.log(
    "obj.scalars():",
    result.map(obj => {
      return obj.scalars()
    }).flatten()
  );

}());

Explanation

Both examples are recursive calls. One method evaluates the key, returning the value when it equals the search key. The other method evaluates the type and returns a value if it is not an object (it's a scalar).

Because map() is used, there is the possibility for undefined values. This is why filter() is called, in order to filter out those values. What's returned by the search functions is an array (potentially an array-of-arrays), which is why flatten() is called, to ensure it is a one-dimentional array.

Upvotes: 1

Prerna Rana
Prerna Rana

Reputation: 95

var multiArr =[];
var arr = [];
function deepTraverse(obj) {
    if( typeof obj == "object" ) {
        $.each(obj, function(k,v) {
           deepTraverse(v);
        });
    }
    else {
        arr.push(obj);
    }
}

$.each(result,function(k,v){
deepTraverse(v);
multiArr.push(arr);
arr = [];
});

console.log(multiArr);

multiArr will contain array of arrays. I hope this helps.

Upvotes: 1

Faraz Babakhel
Faraz Babakhel

Reputation: 664

Get data from result list and into myList one by one. @Jim Dover Try this

 var myList;
    myList.push(result[0].id);
    myList.push(result[0].employeeDetails.id);
    myList.push(result[0].employeeDetails.version);

Or Simply

    result.forEach(function(item,index) {
var TempList;
        TempList.push(item.id);
            TempList.push(item.employeeDetails.id);
            TempList.push(item.employeeDetails.version);

    myList.push(TempList);
    });

Upvotes: 1

Harsheet
Harsheet

Reputation: 628

Try this for any nested JSON -

var result = [{
"id": 89304,
"employeeDetails": {
    "id": 102524,
    "version": 9,
    "Address": { 
          "Country": "US",
          "City": "LA"
  }
}
}];

function get_it(obj){
    for(var prop in obj){
        if(typeof obj[prop]=='object'){
            // object
            get_it(obj[prop]);
        }else{
            // something else
            console.log(obj[prop]+'.');
        }
    }
}

get_it(result);

Upvotes: 1

RITESH ARORA
RITESH ARORA

Reputation: 497

result is itself a array which keys are by default 0,1,2 so that you are getting 0

This is actually what you want

var result = [{
  "id": 89304,
  "employeeDetails": {
    "id": 102524,
    "version": 9
  }
}];

var finalresult = [];
result.forEach(function(record) {
  console.log(getObjValue(record));
})


function getObjValue(obj) {
  var keys = Object.keys(obj);
  for (i = 0; i < keys.length; i++) {
    if (typeof obj[keys[i]] == 'object') {
      getObjValue(obj[keys[i]]);
    } else {
      finalresult.push(obj[keys[i]])
    }
  }
  return finalresult
}

Upvotes: 1

kevguy
kevguy

Reputation: 4438

Just loop through the results array, this should do the trick.

var result = [
  {
    "id": 89304,
    "employeeDetails": {
    "id": 102524,
    "version": 9
    }
  },
  {
    "id": 89123,
    "employeeDetails": {
    "id": 102456,
    "version": 18
    }
  }
];

var arr1 = result.map(function(item){
    return [item.id, item.employeeDetails.id, item.employeeDetails.version];
});


/* ES6 Syntax */
let arr2 = result.map((item) => [item.id, item.employeeDetails.id, item.employeeDetails.version]);

console.log(arr1);
console.log(arr2);

Upvotes: 3

liamta
liamta

Reputation: 113

It's because 'result' is actually an Array so the key that's being outputted is the key for the WHOLE object within the array.

To extract the values from the object you'll first have to iterate over the array and then for EACH of the items then iterate over the keys (Object.keys(obj)).

Here's a rough example for you to work off of, hope it helps.

var result = [{
"id": 89304,
"employeeDetails": {
    "id": 102524,
    "version": 9
}
}];


for (var i = 0; i < result.length; i++) {

  var item = result[i];

  Object.keys(item).forEach(function(key) {

    console.log(item[key]); // This will provide you the value for each key.

  });

}

As one of your properties inside the object is also and object, you'll have to check for that and then further iterate over it.

Upvotes: 1

g3ctong
g3ctong

Reputation: 86

You can write a recursive function the returns the values as a list. Just iterate through the keys with a forEach and if value is an object call itself.

Upvotes: 1

Related Questions