-2

I have sample JSON like this

`{
  values:[{
    "name": "Base Url",
    "url": "https://kubemanagement-prod.kohls.com"
  },
  {
    "name": "Base Url newwww",
    "url": "https://batman.com"
  }]
}`

Currently when I add this paticular JSON to the lodash _.keys gives me the result ["0", "1"] which is basically the index of first and second object 0 and 1.

What I exactly want is to retrieve all the keys of the JSON object including sub object properties as well. In this case ["values","0", "1","name","url"]

Does anyone knows a lodash method or a mechanism to retrieve all the keys given in complex JSON object to nth level?

language : Angular + Typescript

4
  • 1
    JSON is a textual notation for data exchange. (More here.) If you're dealing with JavaScript source code, and not dealing with a string, you're not dealing with JSON. What you have isn't a "JSON object," it's an array. Commented Jul 2, 2019 at 14:12
  • Please check now edited more meaningful manner Commented Jul 2, 2019 at 14:18
  • Possible duplicate of How to get keys (path to) the deepest nested object in a javascript nested object Commented Jul 2, 2019 at 14:46
  • Makes no difference (and still isn't JSON). :-) Commented Jul 2, 2019 at 14:46

4 Answers 4

2

This function recursively gets the keys from an objects tree, using _.keys() and _.flatMap() and _.union() to combine lists of keys, and get only the unique values:

const getAllKeys = obj => _.union(
  _.keys(obj),
  _.flatMap(obj, o => _.isObject(o) ? getAllKeys(o) : [])
)

const arr = {"values": [{"name":"Base Url","url":"https://kubemanagement-prod.kohls.com"},{"name":"Base Url newwww","url":"https://batman.com"}]}

const result = getAllKeys(arr)

console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script>

And the same idea without lodash, using Object.values() and Array.flatMap() to iterate the current object (or array), and Array.concat() and a Set to make the keys unique:

const getAllKeys = obj => [...new Set([].concat(
  Object.keys(obj),
  Object.values(obj).flatMap(o => typeof o === 'object' ? getAllKeys(o) : [])
))]

const arr = {"values": [{"name":"Base Url","url":"https://kubemanagement-prod.kohls.com"},{"name":"Base Url newwww","url":"https://batman.com"}]}

const result = getAllKeys(arr)

console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script>

Without array indexes:

const getAllKeys = obj => _.union(
  _.isArray(obj) ? [] : _.keys(obj),
  _.flatMap(obj, o => _.isObject(o) ? getAllKeys(o) : [])
)

const arr = {"values": [{"name":"Base Url","url":"https://kubemanagement-prod.kohls.com"},{"name":"Base Url newwww","url":"https://batman.com"}]}

const result = getAllKeys(arr)

console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script>

Sign up to request clarification or add additional context in comments.

6 Comments

Looks like the edit fixes the issue I raised, nice!
Would this solution works for any dynamic JSON object with complex structure? Ex: can have arrays inside even.?
Both solutions handle dynamic structures of objects and arrays.
Sorry for the fustration it works fine.. I have put semicolan accidently... Thanks for the answer.. Marked as correct answer.
Sure. Added another answer without the indexes.
|
2

You don't need lodash for this, Object.keys is sufficient. You just write a recursive function, writing to a Set, perhaps converting to array when you're done:

const array = [
  {
    "name": "Base Url",
    "url": "https://kubemanagement-prod.kohls.com"
  },
  {
    "name": "Base Url newwww",
    "url": "https://batman.com"
  }
];

function addAll(set, entries) {
    for (const entry of entries) {
        set.add(entry);
    }
    return set;
}

function allKeys(obj/*: object|array*/, keys/*: Set<string>*/ = new Set()) {
    addAll(keys, Object.keys(obj));
    for (const entry of Object.values(obj)) {
        if (entry && typeof entry === "object") {
            allKeys(entry, keys);
        }
    }
    return keys;
}

console.log([...allKeys(array)]);

Or using the structure in your edit:

const array = {
  values:[{
    "name": "Base Url",
    "url": "https://kubemanagement-prod.kohls.com"
  },
  {
    "name": "Base Url newwww",
    "url": "https://batman.com"
  }]
}

function addAll(set, entries) {
    for (const entry of entries) {
        set.add(entry);
    }
    return set;
}

function allKeys(obj/*: object|array*/, keys/*: Set<string>*/ = new Set()) {
    addAll(keys, Object.keys(obj));
    for (const entry of Object.values(obj)) {
        if (entry && typeof entry === "object") {
            allKeys(entry, keys);
        }
    }
    return keys;
}

console.log([...allKeys(array)]);

Comments

1

How about

const arr = {"values": [{"name":"Base Url","url":"https://kubemanagement-prod.kohls.com"},{"name":"Base Url newwww","url":"https://batman.com"}]}

let result1 = Object.keys(arr) // get the object keys which is "values"
let result2 = Object.keys(arr[result1]); // get the keys of the object name "0,1" here
let result3 = Object.keys(arr[result1][0]); // get property names of one object "name and url" here
let resutltant = result1.concat(result2, result3) // "merge array"
console.log(resutltant)

Assuming that your object properties names will remain constant

Comments

-1

If you use typescript why don't use Object.entries or Object.values to do that?

You need to add to tsconfig the next line:

lib: [ ...... "es2018", ]

Comments

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.