Convert JavaScript string in dot notation into an object reference

前端 未结 27 3034
梦如初夏
梦如初夏 2020-11-21 05:09

Given a JS object

var obj = { a: { b: \'1\', c: \'2\' } }

and a string

\"a.b\"

how can I convert the stri

相关标签:
27条回答
  • 2020-11-21 05:34

    Using object-scan seems a bit overkill, but you can simply do

    const objectScan = require('object-scan');
    
    const get = (obj, p) => objectScan([p], { abort: true, rtn: 'value' })(obj);
    
    const obj = { a: { b: '1', c: '2' } };
    
    console.log(get(obj, 'a.b'));
    // => 1
    
    console.log(get(obj, '*.c'));
    // => 2
    

    There are a lot more advanced examples in the readme.

    0 讨论(0)
  • 2020-11-21 05:35

    It's not clear what your question is. Given your object, obj.a.b would give you "2" just as it is. If you wanted to manipulate the string to use brackets, you could do this:

    var s = 'a.b';
    s = 'obj["' + s.replace(/\./g, '"]["') + '"]';
    alert(s); // displays obj["a"]["b"]
    
    0 讨论(0)
  • 2020-11-21 05:36

    you could also use lodash.get

    You just install this package (npm i --save lodash.get) and then use it like this:

    const get = require('lodash.get');
    
    const myObj = { user: { firstName: 'Stacky', lastName: 'Overflowy' }, id: 123 };
    
    console.log(get(myObj, 'user.firstName')); // prints Stacky
    console.log(get(myObj, 'id')); //prints  123
    
    //You can also update values
    get(myObj, 'user').firstName = John;
    
    0 讨论(0)
  • 2020-11-21 05:37

    This is my extended solution proposed by: ninjagecko

    For me simple string notation was not enough, so below version supports things like:

    index(obj, 'data.accounts[0].address[0].postcode');

    /**
     * Get object by index
     * @supported
     * - arrays supported
     * - array indexes supported
     * @not-supported
     * - multiple arrays
     * @issues:
     *  index(myAccount, 'accounts[0].address[0].id') - works fine
     *  index(myAccount, 'accounts[].address[0].id') - doesnt work
     * @Example:
     * index(obj, 'data.accounts[].id') => returns array of id's
     * index(obj, 'data.accounts[0].id') => returns id of 0 element from array
     * index(obj, 'data.accounts[0].addresses.list[0].id') => error
     * @param obj
     * @param path
     * @returns {any}
     */
    var index = function(obj, path, isArray?, arrIndex?){
    
        // is an array
        if(typeof isArray === 'undefined') isArray = false;
        // array index,
        // if null, will take all indexes
        if(typeof arrIndex === 'undefined') arrIndex = null;
    
        var _arrIndex = null;
    
        var reduceArrayTag = function(i, subArrIndex){
            return i.replace(/(\[)([\d]{0,})(\])/, (i) => {
                var tmp = i.match(/(\[)([\d]{0,})(\])/);
                isArray = true;
                if(subArrIndex){
                    _arrIndex =  (tmp[2] !== '') ? tmp[2] : null;
                }else{
                    arrIndex =  (tmp[2] !== '') ? tmp[2] : null;
                }
                return '';
            });
        }
    
        function byIndex(obj, i) {
            // if is an array
            if(isArray){
                isArray = false;
                i = reduceArrayTag(i, true);
                // if array index is null,
                // return an array of with values from every index
                if(!arrIndex){
                    var arrValues = [];
                    _.forEach(obj, (el) => {
                        arrValues.push(index(el, i, isArray, arrIndex));
                    })
                    return arrValues;
                }
                // if array index is specified
                var value = obj[arrIndex][i];
                if(isArray){
                    arrIndex = _arrIndex;
                }else{
                    arrIndex = null;
                }
                return value;
            }else{
                // remove [] from notation,
                // if [] has been removed, check the index of array
                i = reduceArrayTag(i, false);
                return obj[i]
            }
        }
    
        // reduce with byIndex method
        return path.split('.').reduce(byIndex, obj)
    }
    
    0 讨论(0)
  • 2020-11-21 05:37

    here's my 10 cents to case, bellow function will get/set based on path provided,.. sure u can improve it, remove || and replace it with Object.hasOwnProperty if you do care about false values mistakenly,

    i tested it with a.b.c and a.b.2.c {a:{b:[0,1,{c:7}]}} and its works for both setting and getting :).

    cheerz

    function helper(obj, path, setValue){
      const l = String(path).split('.');
      return l.reduce((o,i, idx)=>{
       if( l.length-idx===1)  { o[i] = setValue || o[i];return setValue ? obj : o[i];}
      o[i] = o[i] || {};
       return o[i];
      }, x)
    }
    
    0 讨论(0)
  • 2020-11-21 05:39

    If you wish to convert any object that contains dot notation keys into an arrayed version of those keys you can use this.


    This will convert something like

    {
      name: 'Andy',
      brothers.0: 'Bob'
      brothers.1: 'Steve'
      brothers.2: 'Jack'
      sisters.0: 'Sally'
    }
    

    to

    {
      name: 'Andy',
      brothers: ['Bob', 'Steve', 'Jack']
      sisters: ['Sally']
    }
    

    convertDotNotationToArray(objectWithDotNotation) {
    
        Object.entries(objectWithDotNotation).forEach(([key, val]) => {
    
          // Is the key of dot notation 
          if (key.includes('.')) {
            const [name, index] = key.split('.');
    
            // If you have not created an array version, create one 
            if (!objectWithDotNotation[name]) {
              objectWithDotNotation[name] = new Array();
            }
    
            // Save the value in the newly created array at the specific index 
            objectWithDotNotation[name][index] = val;
            // Delete the current dot notation key val
            delete objectWithDotNotation[key];
          }
        });
    
    }
    
    0 讨论(0)
提交回复
热议问题