0

This is a follow-up question to this: getPathValue() function for deep objects with arrays and with packed JSON

The accepted answer works very well in most situations:

function getPathValue(object, path) {
    return path
       .replace(/\[/g, '.')
       .replace(/\]/g, '')
       .split('.')
       .reduce(function (o, k) {
           return (typeof o === 'string' ? JSON.parse(o) : (o || {}))[k];
       }, object);
}

I now have a new requirement. I need it to work with arrays in the root level. For example, this object:

[{"currencyPair":"EUR/USD","timestamp":"1546028298698","bidBig":"1.14","bidPips":"450","offerBig":"1.14","offerPips":"457","high":"1.14253","low":"1.14732","open":"1.14305"},{"currencyPair":"USD/JPY","timestamp":"1546028299095","bidBig":"110.","bidPips":"326","offerBig":"110.","offerPips":"336","high":"110.222","low":"111.062","open":"111.012"},{"currencyPair":"GBP/USD","timestamp":"1546028246468","bidBig":"1.26","bidPips":"974","offerBig":"1.26","offerPips":"988","high":"1.26350","low":"1.27087","open":"1.26505"},{"currencyPair":"EUR/GBP","timestamp":"1546028296658","bidBig":"0.90","bidPips":"127","offerBig":"0.90","offerPips":"140","high":"0.90034","low":"0.90601","open":"0.90355"},{"currencyPair":"USD/CHF","timestamp":"1546028296551","bidBig":"0.98","bidPips":"470","offerBig":"0.98","offerPips":"481","high":"0.97896","low":"0.99113","open":"0.98854"},{"currencyPair":"EUR/JPY","timestamp":"1546028299289","bidBig":"126.","bidPips":"322","offerBig":"126.","offerPips":"336","high":"126.256","low":"127.204","open":"127.008"},{"currencyPair":"EUR/CHF","timestamp":"1546028296543","bidBig":"1.12","bidPips":"714","offerBig":"1.12","offerPips":"726","high":"1.12146","low":"1.13180","open":"1.12920"},{"currencyPair":"USD/CAD","timestamp":"1546028299908","bidBig":"1.36","bidPips":"470","offerBig":"1.36","offerPips":"485","high":"1.35946","low":"1.36613","open":"1.36142"},{"currencyPair":"AUD/USD","timestamp":"1546028296222","bidBig":"0.70","bidPips":"445","offerBig":"0.70","offerPips":"453","high":"0.70238","low":"0.70695","open":"0.70288"},{"currencyPair":"GBP/JPY","timestamp":"1546028297767","bidBig":"140.","bidPips":"123","offerBig":"140.","offerPips":"148","high":"139.495","low":"140.628","open":"140.462"}]

I want to retain all of the functionality of the previously accepted answer, but in addition, I'd like to be able to retrieve specific array elements and even specific key values within specific array elements. For example,

value = getPathValue(obj, '[0]');

...which should return only this string:

{"currencyPair":"EUR/USD","timestamp":"1546028298698","bidBig":"1.14","bidPips":"450","offerBig":"1.14","offerPips":"457","high":"1.14253","low":"1.14732","open":"1.14305"}

or

value = getPathValue(obj, '[3].bidPips');

...which would return:

"0.90"
Excel Hero
  • 14,253
  • 4
  • 33
  • 40

2 Answers2

1

Change:

.split('.')

By:

.split('.').filter(Boolean)

It will remedy a dot that got placed at the very beginning of the string, which is what happens when the input starts with a [, like in [0].

Demo:

function getPathValue(object, path) {
    return path
       .replace(/\[/g, '.')
       .replace(/\]/g, '')
       .split('.').filter(Boolean)
       .reduce(function (o, k) {
           return (typeof o === 'string' ? JSON.parse(o) : (o || {}))[k];
       }, object);
}

var obj = [{"currencyPair":"EUR/USD","timestamp":"1546028298698","bidBig":"1.14","bidPips":"450","offerBig":"1.14","offerPips":"457","high":"1.14253","low":"1.14732","open":"1.14305"},{"currencyPair":"USD/JPY","timestamp":"1546028299095","bidBig":"110.","bidPips":"326","offerBig":"110.","offerPips":"336","high":"110.222","low":"111.062","open":"111.012"}];

value = getPathValue(obj, '[0].bidPips');

console.log(value);

It can be done easier though, by replacing the replace and split calls by one match call:

function getPathValue(object, path) {
    return path
       .match(/[^[\].]+/g)
       .reduce(function (o, k) {
           return (typeof o === 'string' ? JSON.parse(o) : (o || {}))[k];
       }, object);
}

var obj = [{"currencyPair":"EUR/USD","timestamp":"1546028298698","bidBig":"1.14","bidPips":"450","offerBig":"1.14","offerPips":"457","high":"1.14253","low":"1.14732","open":"1.14305"},{"currencyPair":"USD/JPY","timestamp":"1546028299095","bidBig":"110.","bidPips":"326","offerBig":"110.","offerPips":"336","high":"110.222","low":"111.062","open":"111.012"}];
value = getPathValue(obj, '[0].bidPips');

console.log(value);
trincot
  • 317,000
  • 35
  • 244
  • 286
0

You could remove a leading dot before splitting.

function getValue(object, path) {
    return path
       .replace(/\[/g, '.')
       .replace(/\]/g, '')
       .replace(/^\./, '')
       .split('.')
       .reduce(function (o, k) {
           return (typeof o === 'string' ? JSON.parse(o) : (o || {}))[k];
       }, object);
}

var obj = [{"currencyPair":"EUR/USD","timestamp":"1546028298698","bidBig":"1.14","bidPips":"450","offerBig":"1.14","offerPips":"457","high":"1.14253","low":"1.14732","open":"1.14305"},{"currencyPair":"USD/JPY","timestamp":"1546028299095","bidBig":"110.","bidPips":"326","offerBig":"110.","offerPips":"336","high":"110.222","low":"111.062","open":"111.012"},{"currencyPair":"GBP/USD","timestamp":"1546028246468","bidBig":"1.26","bidPips":"974","offerBig":"1.26","offerPips":"988","high":"1.26350","low":"1.27087","open":"1.26505"},{"currencyPair":"EUR/GBP","timestamp":"1546028296658","bidBig":"0.90","bidPips":"127","offerBig":"0.90","offerPips":"140","high":"0.90034","low":"0.90601","open":"0.90355"},{"currencyPair":"USD/CHF","timestamp":"1546028296551","bidBig":"0.98","bidPips":"470","offerBig":"0.98","offerPips":"481","high":"0.97896","low":"0.99113","open":"0.98854"},{"currencyPair":"EUR/JPY","timestamp":"1546028299289","bidBig":"126.","bidPips":"322","offerBig":"126.","offerPips":"336","high":"126.256","low":"127.204","open":"127.008"},{"currencyPair":"EUR/CHF","timestamp":"1546028296543","bidBig":"1.12","bidPips":"714","offerBig":"1.12","offerPips":"726","high":"1.12146","low":"1.13180","open":"1.12920"},{"currencyPair":"USD/CAD","timestamp":"1546028299908","bidBig":"1.36","bidPips":"470","offerBig":"1.36","offerPips":"485","high":"1.35946","low":"1.36613","open":"1.36142"},{"currencyPair":"AUD/USD","timestamp":"1546028296222","bidBig":"0.70","bidPips":"445","offerBig":"0.70","offerPips":"453","high":"0.70238","low":"0.70695","open":"0.70288"},{"currencyPair":"GBP/JPY","timestamp":"1546028297767","bidBig":"140.","bidPips":"123","offerBig":"140.","offerPips":"148","high":"139.495","low":"140.628","open":"140.462"}],
    value = getValue(obj, '[0]');
    
console.log(value)
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
  • Thanks again. This time I chose the other answer... basically because it was more concise yet still seems to work in all cases. If your answer here avoids some hiccup that I'm not seeing in trincot's simplified answer, please let me know. – Excel Hero Jan 01 '19 at 04:56