The correct way to merge JSON object

I. Introduction

"JSON object consolidation" is the front-end development environment for the development and NodeJS a very common operation. Developers typically cycle through or by some libraries or encapsulation methods defined JavaScript ECMAScript Object.assign 2015 () is achieved.

Second, the common way merger

1. Method a: Method to loop through

function extend() {
    var length = arguments.length;
    if(length == 0)return {};
    if(length == 1)return arguments[0];
    var target = arguments[0] || {};
    for (var i = 1; i < length; i++) {
        var source = arguments[i];
        for (var key in source) {
            if (source.hasOwnProperty(key)) {
                target[key] = source[key];
            }
        }
    }
     
    return target;
}
const obj1 = { a: 1, b: 2 };
const obj2 = { b: 3, c: 4, d: 5 };
const result = extend(obj1, obj2);
console.log(result);//{ a: 1, b: 3, c: 4, d: 5 }

 

2. Method two: Object.assign ()

const obj1 = { a: 1, b: 2 };
const obj2 = { b: 3, c: 4, d: 5 };
const result = Object.assign(obj1, obj2);
console.log(result);//{ a: 1, b: 3, c: 4, d: 5 }

 

3. Method three: Using jQuery plugin

const jsdom = require("jsdom");
const { JSDOM } = jsdom;
const { window } = new JSDOM(`<!DOCTYPE html>`);
const $ = require('jQuery')(window);
const obj1 = { a: 1, b: 2 };
const obj2 = { b: 3, c: 4, d: 5 };
const result = $.extend(obj1, obj2);
console.log(result);//{ a: 1, b: 3, c: 4, d: 5 }

 

From the test results, more than three programs can get the desired results.

Third, Advanced

But in the actual project, the need to merge objects is often not so simple, such as merging the following objects:

= chartScheme the let { 
    Series: [{ 
            name: 'Local' , 
            type: 'bar' , 
            Stack: 'Analysis reside' , 
        }, 
        { 
            name: 'province' , 
            type: 'bar' , 
            Stack: 'Analysis residing ' , 
        } 
    ] 
};
let chartStyle = {
    grid: {
        top: '25%',
        bottom: '30',
        left: '15%',
        right: '5%'
    },
    series: [{
            barWidth: '10px',
            itemStyle: {
                color: '#4AC6E7'
            }
        },
        {
            barWidth: '10px',
            itemStyle: {
                color: '#73C642'
            }
        }
    ]
};
let chartStyle2 = {
    series: [{
            lineStyle: {
                normal: {
                    color: '#36d0f3'
                }
            },
            itemStyle: {
                normal: {
                    color: '#36d0f3'
                }
            }
        },
        {
            lineStyle: {
                normal: {
                    color: '#36d0f3'
                }
            },
            itemStyle: {
                normal: {
                    color: '#36d0f3'
                }
            }
        }
    ]
};
let chartData = {
    series: [{
            data: [35, 60, 50, 80, 80, 55, 70, 70],
        },
        {
            data: [60, 80, 60, 45, 80, 55, 60, 20],
        }
    ]
};

 

The combined goal is to preserve the properties of all the non-dot, the dot attribute atoms foregoing parameters back cover parameters.

The following tests were combined with the above-described done in several ways:

1. Test method

let result = extend(chartScheme, chartStyle, chartStyle2, chartData);
console.log(result);

 

As a result, non-atomic property is covered, not meet the requirements:

result = {
    "series": [{
        "data": [35, 60, 50, 80, 80, 55, 70, 70]
    }, {
        "data": [60, 80, 60, 45, 80, 55, 60, 20]
    }],
    "grid": {
        "top": "25%",
        "bottom": "30",
        "left": "15%",
        "right": "5%"
    }
}

 

2. Test Method II

let result = Object.assign(chartScheme, chartStyle, chartStyle2, chartData);
console.log(result);

 

The results are as follows, with a different method does not meet the requirements:

result = {
    "series": [{
        "data": [35, 60, 50, 80, 80, 55, 70, 70]
    }, {
        "data": [60, 80, 60, 45, 80, 55, 60, 20]
    }],
    "grid": {
        "top": "25%",
        "bottom": "30",
        "left": "15%",
        "right": "5%"
    }
}

 

3. Test Method Three

let result = $.extend(chartScheme, chartStyle, chartStyle2, chartData);
console.log(JSON.stringify(result));

 

The results are as follows, or not to request:

result = {
    "series": [{
        "data": [35, 60, 50, 80, 80, 55, 70, 70]
    }, {
        "data": [60, 80, 60, 45, 80, 55, 60, 20]
    }],
    "grid": {
        "top": "25%",
        "bottom": "30",
        "left": "15%",
        "right": "5%"
    }
}

 

Obviously, the above three methods when combined complex objects are defective, the combined properties of non-target object are atomic properties of the same name of the source object directly behind the cover.

But jQuery's "extend ()" method has two prototypes:

$.extend( target [, object1 ] [, objectN ] )
$.extend( [deep ], target, object1 [, objectN ] )

 

With the above is the first prototype, the second prototype there is a deep copy option, "$ .extend ()" is the first argument passed "true", you can try:

let result = $.extend(true, chartScheme, chartStyle, chartStyle2, chartData);
console.log(JSON.stringify(result));

 

 

The results are as follows:

let result = $.extend(true, chartScheme, chartStyle, chartStyle2, chartData);
console.log(JSON.stringify(result));
result = {
    "series": [{
        "name": "本地",
        "type": "bar",
        "stack": "驻留分析",
        "barWidth": "10px",
        "itemStyle": {
            "color": "#4AC6E7",
            "normal": {
                "color": "#36d0f3"
            }
        },
        "lineStyle": {
            "normal": {
                "color": "#36d0f3"
            }
        },
        "data": [35, 60, 50, 80, 80, 55, 70, 70]
    }, {
        "name": "省内",
        "type": "bar",
        "stack": "驻留分析",
        "barWidth": "10px",
        "itemStyle": {
            "color": "#73C642",
            "normal": {
                "color": "#36d0f3"
            }
        },
        "lineStyle": {
            "normal": {
                "color": "#36d0f3"
            }
        },
        "data": [60, 80, 60, 45, 80, 55, 60, 20]
    }],
    "grid": {
        "top": "25%",
        "bottom": "30",
        "left": "15%",
        "right": "5%"
    }
}

 

 

From the results, the combined data is complete, and then modify the source objects merge, did not affect the consolidated results, showing that the copy is merged deep copy, not a reference copy, is a good API. However, due to the jQuery library node environments it is quite troublesome, efficiency mobile applications and end in the SPA is not too high, it is necessary to organize a more efficient libraries for everyday use.

Fourth, efficient and reliable combined method

1. Key Code

After comparative study of a number of front-end js library, put together a library, the key code is as follows:

/ * * 
 * @Description clone 
 * be cloned object types: 
 * Plain Object, the Array, the TypedArray, Number, String, null, undefined. 
 * Assignment of data types directly using the raw data: 
 * BUILTIN_OBJECT 
 * user-defined classes examples cloned into a normal object without attribute prototype. 
 @Method clone * 
 * @param {} * Source 
 * @return new new} * { 
 * / 
clone (Source) { 
    IF (Source == null || typeof Source == 'Object'! ) {
         Return Source; 
    } 
    var Result = Source;
     var typeStr = the this .objToString.call (Source);
     IF (typeStr === '[object Date]') {
        result = this.cloneDate(source);
    }
    else if (typeStr === '[object RegExp]') {
        result = this.cloneRegExp(source);
    }
    else if (typeStr === '[object Function]') {
        result = this.cloneFunction(source);
    }
    else if (typeStr === '[object Array]') {
        result = [];
        for (var i = 0, len = source.length; i < len; i++) {
            result[i] = this.clone(source[i]);
        }
    }
    else if (this.TYPED_ARRAY[typeStr]) {
        var Ctor = source.constructor;
        if (source.constructor.from) {
            result = Ctor.from(source);
        }
        else {
            result = new Ctor(source.length);
            for (var i = 0, len = source.length; i < len; i++) {
                result[i] = this.clone(source[i]);
            }
        }
    }
    else if (!this.BUILTIN_OBJECT[typeStr] && !this.isDom(source)) {
        result = {};
        for (var key in source) {
            if (this.hasOwn(source, key)) {
                result[key] = this.clone(source[key]);
            }
        }
    }
    return result;
},
/**
 * @Description 合并函数
 * @method merge
 * @param {*} target
 * @param {*} source
 * @param {boolean} [overwrite=false]
 * @return {Object}
 */
merge(target, source, overwrite) {
    // We should escapse that source is string
    // and enter for ... in ...
    if (!this.isObject(source) || !this.isObject(target)) {
        return overwrite ? this.clone(source) : target;
    }
    for (var key in source) {
        if (this.hasOwn(source, key)) {
            var targetProp = target[key];
            var sourceProp = source[key];
            if (this.isObject(sourceProp)
                && this.isObject(targetProp)
                && !this.isDom(sourceProp)
                && !this.isDom(targetProp)
                && !this.isBuiltInObject(sourceProp)
                && !this.isBuiltInObject(targetProp)
            ) {
                // 如果需要递归覆盖,就递归调用merge
                this.merge(targetProp, sourceProp, overwrite);
            }
            else if(overwrite ||! (Key in target)) {
                 // case otherwise deal only overwrite is true, or do not have this property in the target object 
                // NOTE, the target [key] is when there is no direct coverage 
                target [key ] = the this .clone (Source [Key], to true ); 
            } 
        } 
    } 
    return target; 
}

 

2. The complete code with the library

The complete code in  HTTP: //192.168.xy/z/merge-util , the code has been processed, the environment and browser compatible node environment, npm package has been posted to the company's internal library: HTTP: //192.168.xy: z / # the Browse / the Browse: Merge-util .

Fifth, use

1. Node Environment

Use the command with a temporary registry npm install package:

npm --registry http://192.168.x.y:z/my-repository/ install merge-util

 

Persistent registry settings or install package:

npm config set registry http://192.168.x.y:z/my-repository/
npm install merge-util
const mergeUtil = require('merge-util');
let result = mergeUtil.mergeAll([{},chartScheme, chartStyle, chartStyle2, chartData], true);
console.log(JSON.stringify( result));

 

2. The browser environment

Npm command via the package to be installed locally, or downloaded from GitHub index.js file, and reference can be used in the html file:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>Merge-test</title>
        <script src="./rs-merge-util.js"></script>
        <script src="./testdata.js"></script>
    </head>
    <body>
        <script>
            const result = mergeUtil.mergeAll([{}, chartScheme, chartStyle, chartStyle2, chartData0, chartData], true);
            console.log(JSON.stringify(result));
        </script>
    </body>
</html>

 

 

Guess you like

Origin www.cnblogs.com/Jaffray/p/11627062.html