简体   繁体   中英

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.

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); 

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

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.

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);
    });

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.

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
}

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); 

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.

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.

//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']

]

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); 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM