3

I have a highly nested JSON structure where I can pull out individual information like this

let result = data["a"]["b"][0]["c"]["d"][0]["e"][0]

what is an elegant way to pull the data out? Also, can the result be assigned to null or undefined when along the way any of a,b,c,d,e does not exist or when the array does not contain element 0?

Satpal
  • 126,885
  • 12
  • 146
  • 163
Se7enDays
  • 2,343
  • 2
  • 13
  • 20
  • 1
    [Optional chaining](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining) – ASDFGerte Sep 08 '20 at 10:38
  • My favorite solution is the `_try` function in the linked question for such long navigation, until the optional chaining operator will be supported in all the targets – Cristian Traìna Sep 08 '20 at 10:39
  • @CristianTraìna this is not necessary anymore, as it's now within the ECMA standard and is supported either through transpilation (using webpack) for older targets or directly in the JS engines (node and browsers). – zmo Sep 08 '20 at 10:42
  • @zmo I agree, but not everyone is using Babel :) some still write JavaScript for the browser. Btw the linked question contains also a reference to optional chaining operator – Cristian Traìna Sep 08 '20 at 10:44
  • I'm not disagreeing with the closure of the question as duplicate, I actually just added my vote. Though I believe the optional chaining should be preferred to the `_try` function, as now it is support by the major browsers, it's in the standard and for the backward compatibility there's babel. – zmo Sep 08 '20 at 17:18

3 Answers3

1

With latest Javascript you can use the optional chaining operator:

let result = data?.a?.b?.[0]?.c?.d?.[0]?.e?.[0]

zmo
  • 22,917
  • 4
  • 48
  • 82
0

I'd say the easiest option would be an optional chaining operator or something, but I believe the right way to do this is something like JSONPath.

There might be other libraries (e.g. like jsonpath one or jsonpath-plus) which allows you to do the same.

JSONPath is XPath for JSON.

JSON Example:

{ "store": {
    "book": [ 
      { "category": "reference",
        "author": "Nigel Rees",
        "title": "Sayings of the Century",
        "price": 8.95
      },
      { "category": "fiction",
        "author": "Evelyn Waugh",
        "title": "Sword of Honour",
        "price": 12.99
      }
    ],
    "bicycle": {
      "color": "red",
      "price": 19.95
    }
  }
}

And this is how you can get the authors of all books in the store using JSONPath expression:

$.store.book[*].author

You can use it in JavaScript:

const o = { /*...*/ },  // the 'store' JSON object from above
res1 = jsonPath(o, "$..author").toJSONString(); // all authors JSONPath expression
res2 = jsonPath(o, "$..author", {resultType:"PATH"}).toJSONString();
ikos23
  • 3,661
  • 9
  • 30
  • 47
0

You can write a function path that gets an array of properties to access and an object to read from:

  • The function is curried so you can build a function that access a specific path and reuse it with different objects
  • The reduce drills down the object until undefined or the end of the path is reached.

const path = p => o =>
  p.reduce( (res, pp) =>
              res === undefined ? res : res[pp]
          , o
          );
          
          
const abcd = path(['a', 'b', 'c', 'd']);

console.log(abcd({}));
console.log(abcd({a: 1}));
console.log(abcd({a: {b: {}}}));
console.log(abcd({a: {b: {c: {d: 42}}}}));
customcommander
  • 11,496
  • 3
  • 35
  • 53