How to reliably hash JavaScript objects?

前端 未结 6 1848
天涯浪人
天涯浪人 2021-02-06 21:53

Is there a reliable way to JSON.stringify a JavaScript object that guarantees that the ceated JSON string is the same across all browsers, node.js and so on, given that the Java

6条回答
  •  不思量自难忘°
    2021-02-06 22:32

    After trying some hash algorithms and JSON-to-string methods, I found this to work the best (Sorry, it is typescript, can of course be rewritten to javascript):

    // From: https://stackoverflow.com/questions/5467129/sort-javascript-object-by-key
    function sortObjectKeys(obj){
        if(obj == null || obj == undefined){
            return obj;
        }
        if(typeof obj != 'object'){ // it is a primitive: number/string (in an array)
            return obj;
        }
        return Object.keys(obj).sort().reduce((acc,key)=>{
            if (Array.isArray(obj[key])){
                acc[key]=obj[key].map(sortObjectKeys);
            }
            else if (typeof obj[key] === 'object'){
                acc[key]=sortObjectKeys(obj[key]);
            }
            else{
                acc[key]=obj[key];
            }
            return acc;
        },{});
    }
    let xxhash64_ObjectToUniqueStringNoWhiteSpace = function(Obj : any)
    {
        let SortedObject : any = sortObjectKeys(Obj);
        let jsonstring = JSON.stringify(SortedObject, function(k, v) { return v === undefined ? "undef" : v; });
    
        // Remove all whitespace
        let jsonstringNoWhitespace :string = jsonstring.replace(/\s+/g, '');
    
        let JSONBuffer: Buffer = Buffer.from(jsonstringNoWhitespace,'binary');   // encoding: encoding to use, optional.  Default is 'utf8'
        return xxhash.hash64(JSONBuffer, 0xCAFEBABE, "hex");
    }
    

    It used npm module: https://cyan4973.github.io/xxHash/ , https://www.npmjs.com/package/xxhash

    The benefits:

    • This is deterministic
    • Ignores key order (preserves array order)
    • Cross platform (if you can find equivalents for JSON-stringify) JSON-stringify will hopefully will not get a different implementation and the whitespace removal will hopefully make it JSON-formatting independent.
    • 64-bit
    • Hexadecimal string a result
    • Fastest (0.021 ms for 2177 B JSON, 2.64 ms for 150 kB JSON)

提交回复
热议问题