Convert JavaScript string in dot notation into an object reference

前端 未结 27 3584
梦如初夏
梦如初夏 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: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)
    }
    

提交回复
热议问题