How can I simplify access to the values of interest of a Javascript JSON?

2

Context: I am developing an application that consumes several APIs. The JSONs returned by these APIs have their own structure, which is often not the most intuitive for the programmer to exploit. / p>

Example: Suppose I am using an external API, and that this is JSON returned from any route.

{
  "arvore": {
    "avo": {
      "pai": {
        "eu": "pedro"
      }
    }
  }
}

Suppose also that the only information that interests me in this JSON is the value of the key eu . This way, every time I consume this resource and get this JSON, I will have to access my information of interest like this: obj['arvore']['avo']['pai']['eu'] or so obj.arvore.avo.pai.eu , etc.

Problem / nuisance: Access to this information of interest is very verbose. And this may somewhat inhibit the speed of the development process in a larger scenario, anyway.

I was thinking of creating a sort of wrapper for the returned JSONs - of the resources I most use. For example, instead of accessing the key through its actual structure ( obj['arvore']['avo']['pai']['eu'] ), I could simply give obj.eu and then it would have exactly the same result. However, before implementing this, I wanted to raise this discussion here. Thank you very much.

    
asked by anonymous 21.06.2017 / 02:52

3 answers

0

I found a simple solution using static of ECMAScript 6, as follows in the code. In them, I define how to return the path to my information of interest, simple as that.

    var obj = {
        "arvore": {
            "avo": {
                "pai": {
                    "eu": "pedro"
                }
            }
        }
    }

    class Access {
        static getEu(obj) {
            return obj.arvore.avo.pai.eu;
        }
    }

    document.body.innerHTML = Access.getEu(obj);
    
05.07.2017 / 13:43
0

It's a bit far-fetched, but you can do a recursive function that looks for the entries of the object and if the first key of the return is equal to the key that you are looking for, then return that value - otherwise call the function again with the second return value:

const tree = {
  "arvore": {
    "avo": {
      "pai": {
        "eu": {
          "nome": "pedro",
          "familia": "dev"
        }
      }
    }
  }
}

function getObjectValueByKey(key, _pool) {
  const pool = Object.entries(_pool);
  let found = null;

  pool[0].forEach(entry => {
    if (entry === key) {
      found = pool[0][1];
    }
  });

  if (found) return found;
  else return getObjectValueByKey(key, pool[0][1]);
}


const value = getObjectValueByKey('eu', tree);
console.log('value?', value);
    
21.06.2017 / 15:21
0

You can create a function that creates an alias for your object, always pointing to the path defined by the function.

function get(source, path) {
  return path.split('.').reduce((currentValue, propertyName) => {
    return currentValue && currentValue[propertyName]
  }, source);
}

function alias(source, aliasName, path) {
  return Object.defineProperty(source, aliasName, {
    get() {
      return get(this, path);
    }
  });
}

const obj = {
  "arvore": {
    "avo": {
      "pai": {
        "eu": "pedro"
      }
    }
  }
};

const decorated = alias(obj, 'eu', 'arvore.avo.pai.eu');

decorated.eu; // "pedro"

decorated.arvore.avo.pai.eu = "joão";

decorated.eu; // "joão"

If you want multiple aliases:

function aliases(source, aliases) {
  return aliases.reduce((decorated, args) => {
    return alias(decorated, ...args)
  }, source);
}

const decorated = aliases(obj, [
  ['avo', 'arvore.avo'],
  ['pai', 'avo.pai'],
  ['eu', 'pai.eu']
]);
    
05.07.2017 / 14:00