2

I read lots of information on the net and forums but cannot get a solution to my problem. I have the following JSON file:

var data = 
{ "AA" :[{"a1":[{"ab1": [
                     {"ab1a": 10 },
                     {"ab1b": 20 },
                     {"ab1c": 30 },
                     {"ab1d": 40 }
                     ]
            },
            {"ab2":[
                     {"ab1a": 10 },
                     {"ab1b": 20 },
                     {"ab1c": 30 },
                     {"ab1d": 40 }
                    ]
            }
            ]
     }
     ,{"a2":[{"ab3": [
                     {"ab3a": 10 },
                     {"ab3b": 20 },
                     {"ab3c": 30 },
                     {"ab3d": 40 }
                     ]
             },
            {"ab4":[
                     {"ab4a": 10 },
                     {"ab4b": 20 },
                     {"ab4c": 30 },
                     {"ab4d": 40 }
                    ]
            } 
            ]
     }    
    ]
}

I have validated the JSON file. I want to get the keys first for "AA" then "a1" and "a2" and then for "ab1", "ab2" and etc. There are questions and information about values but not the keys. Most probably jQuery might help but I am confused about how to get all the keys.

Any ideas? any hope...!

2

1 Answer 1

0

The key to getting all the keys from an object of unknown size is recursion. Here I have 2 solutions; one Functional and one Object Oriented. Also I created some other data to test with in addition to yours.

Here is the repo with the complete code: https://github.com/vasilionjea/json-keys


The Data:

var data = {
  continents: {
    europe: {
      countries: [
        {
          'country-name': 'italy',
          cities: [
            { 'city-name': 'Rome', title: 'Roma Dolor', population:873, gdb: 301 },
            { 'city-name': 'Venice', title: 'Venice Veggies.', population:456, gdb: 244 }
          ]
        },

        {
          'country-name': 'france',
          cities: [
            { 'city-name': 'Paris', title: 'De Ipsum', population:7123, gdb: 77 },
            { 'city-name': 'Marseille', title: 'La Mipsum', population:73, gdb: 7 }
          ]
        }
      ]
    },

    'north-america': {
      countries: [
        {
          'country-name': 'canada',
          cities: [
            { 'city-name': 'Montreal', title: 'The city of lorem ipsum!', population:99, gdb: 011 },
            { 'city-name': 'Quebec', title: 'Veggie Ipsum.', population:123, gdb: 101 }
          ]
        },
        {
          'country-name': 'usa',
          cities: [
            { 'city-name': 'New York', title: 'Empire State', population:1001001, gdb: 1010 },
            { 'city-name': 'San Francisco', title: 'SF Bridge', population:20123, gdb: 202 }
          ]
        }
      ]
    }
  }
}


The functional way:

/*
 * Functional example.
 * Retrieves all keys from an object of unknown size using recursion.
 */
function _isObject(obj) {
  return Object.prototype.toString.call(obj) === "[object Object]";
}

function _eachKey(obj, callback) {
  Object.keys(obj).forEach(callback);
}

var _container = [];

function collectKeys(data) {
  _eachKey(data, function(key) {
    _container.push(key);

    if (_isObject(data[key])) {
      collectKeys(data[key]);
    }

    if (Array.isArray(data[key])) {
      // Because we're looping through an array and each array's item is an object, 
      // the `collectKeys` function is receiving each object of the array as an argument.
      data[key].forEach(collectKeys);
    }
  });

  return _container;
}

// Execute the function
var myKeys = collectKeys(data);


The Object Oriented way:

/*
 * Object Oriented example.
 * Retrieves all keys from an object of unknown size using recursion.
 */
function JSONKeys(obj) {
  this._container = [];

  if (this._isObject(obj)) {
    // Just a normal object literal.
    this._data = obj;
  } else if (typeof obj === 'string') {
    // Just in case the data was passed in as a valid JSON string.
    this._data = JSON.parse(obj);
  } else {
    throw new Error('The provided argument must be an object literal or a JSON string.');
  }
}

JSONKeys.prototype = {
  constructor: JSONKeys,

  _isObject: function(obj) {
    return Object.prototype.toString.call(obj) === "[object Object]";
  },

  _eachKey: function(obj, callback) {
   // Using `bind(this)` makes sure that the `this` value in the `_collect` method 
   // isn't set to the global object (window).
    Object.keys(obj).forEach(callback.bind(this));
  },

  _recur: function(key, data) {
      // If this key's value is also an object go deeper.
      if (this._isObject(data[key])) {
        this._collect(data[key]);
      }

      if (Array.isArray(data[key])) {
        // * Because we're looping through an array and each array's item is an object, 
        //   the `_collect` method is receiving each object of the array as an argument.
        // * Using `bind(this)` makes sure that the `this` value in the `_collect` method 
        //   isn't set to the global object (window).
        data[key].forEach(this._collect.bind(this));
      }
  },

  _collect: function(data) {
    this._eachKey(data, function(key) {
      this._container.push(key);

      // Continue collecting
      this._recur(key, data);
    });
  },

  getAll: function() {
    this._collect(this._data);
    return this._container;
  }
};

// Create a new instance passing the data.
var keysObject = new JSONKeys(data);
allKeys = keysObject.getAll();
Sign up to request clarification or add additional context in comments.

4 Comments

var keys = $AA[a2][ab3].keys .Is it possible to get onliner with javascript to obtain keys out of ab3.
Yes there is. For example if I have the following data: var person = { addresses: [ {street: '123 main st.', number: 7, city: 'New York'}, {street: '123 first st.', number: 99, city: 'San Francisco', state: 'CA'} ] }, and want to get the keys of the second address in the array, then I can do this: Object.keys(person['addresses'][1]);
I am getting somewhere..! I need to study more about Accessing Object in the Objects. when i tried "Object.keys(data['AA']['a2'][0]);" i get error data['AA']['a2'] is undefined.
That's because data['AA'] is an array and array items can be queried by an integer (this index): data['AA'][0] gives you the first object in the array. So to get a2 you would do data['AA'][0]['a2']. But a2 is also an array, so getting an object in that array you would follow the same pattern. I'm confident you can figure out the rest. :)

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.