繁体   English   中英

Javascript递归地对对象和嵌套对象以及数组进行排序

[英]Javascript recursively order object and nested objects as well as arrays

我正在尝试通过启用按键排序来获得与pythons json.dumps()相同的结果。 它是作为Postman生成请求哈希值的预请求脚本而执行的。 输出需要排序为有效的json,用作哈希输入。 我是javascript的新手,看到许多旧答案都声称javascript中的对象无法排序。 但是,必须有一种在给定条件下生成哈希的解决方案。

  • 对象结构无法更改。
  • 它只需要支持Chrome。
  • 我可以使用图书馆。
  • requestParams可以包含嵌套对象和数组,这些对象和数组需要在任何深度进行排序。

这是我当前的代码。 在Chrome控制台中,sortedResult的对象预览未排序,但是,当我展开对象和子对象时,Chrome控制台将sortedResult显示为已排序,完全符合其应有的方式。 这给我的印象是sortObject在工作。 但是requestOrdered返回有效的json对象,但未排序。 我最初的想法是,也许JSON.stringify()正在对其进行排序。

const requestRebuilt = {"username": user, "password": password, "sTime": time, "function": function,
                 "functionParams": requestParams, "salt": salt};

function sortObject(object){  
    var keys = _.keys(object);
    var sortedKeys = _.sortBy(keys, function(key){  
        //console.log(key);
        return key; 
    });
    var sortedObj = {};
    var sortedObjJson = "";

    for(var index in keys){
        var key = keys[index];
        //console.log(key + ' ' + typeof object[key]);

        if(typeof object[key] == 'object' && !(object[key] instanceof Array)){
            sortedObj[key] = sortObject(object[key]);
        } else if(object[key] instanceof Array) {
            //sortedObj[key] = object[key].sort();
            var arrayLength = object[key].length;
            for (var i = 0; i < arrayLength; i++) {
                sortedObj[key] = sortObject(object[key][i]);
                //console.log(object[key][i]);
            }
        } else {
            sortedObj[key] = object[key];
        }
    }
    return sortedObj;
}
const sortedResult = sortObject(requestRebuilt);
console.log(sortedResult);

const requestOrdered = JSON.stringify(sortedResult);
console.log(requestOrdered);

var hash = CryptoJS.SHA256(requestOrdered).toString();
postman.setGlobalVariable("hash", hash);

输入示例:

{
    "username": "jdoe@mail.com",
    "sTime": "2016-03-04T13:53:37Z",
    "function": "begin",
    "functionParams": {
        "tip": "ABC123FFG",   
        "pad": 4 ,
        "passenger": [{
            "firstName": "John",
            "phone": 1234567890,
            "email": "jdoe@mail.com",
            "dateOfBirth": "1915-10-02T00:00:00Z",
            "bans": {
                "weight": 9,
                "count": 2
            }
        }
    ]},
    "salt": "00d878f5e203",
    "pep": "sdeODQ0T"
}

在python中,这是通过以下操作完成的:

ordered = json.dumps(
   {"username": user, "password": password, "time": time, "function": function, "functionParams": functionParams, "salt": salt}
    sort_keys=True, separators=(',', ':'))

订购结果:

{"function":"begin","functionParams":{"passenger":[{"bans":{"count":2,"weight":9},"dateOfBirth":"1915-10-02T00:00:00Z","email":"jdoe@mail.com","firstName":"John","phone":1234567890}],"pad":4,"tip":"ABC123FFG"},"pep":"sdeODQ0T","salt":"00d878f5e203","sTime":"2016-03-04T13:53:37Z","username":"jdoe@mail.com"}

印刷精美,易于阅读,但实际结果中不应包含空格或

    {
      "function": "begin",
      "functionParams": {
        "passenger": [
          {
            "bans": {
              "count": 2,
              "weight": 9
            },
            "dateOfBirth": "1915-10-02T00:00:00Z",
            "email": "jdoe@mail.com",
            "firstName": "John",
            "phone": 1234567890
          }
        ],
        "pad": 4,
        "tip": "ABC123FFG"
      },
      "pep": "sdeODQ0T",
      "salt": "00d878f5e203",
      "sTime": "2016-03-04T13:53:37Z",
      "username": "jdoe@mail.com"
    }

常见的误解是javascript中“对象键未排序”。 MDN指出

尽管ECMAScript使对象的迭代顺序取决于实现的实现,但似乎所有主流浏览器都基于最早出现的最早添加属性(至少对于原型中没有的属性)支持迭代顺序。

ES2015将此行为标准制定为

对于每个自己的O的属性键P(它是String而不是整数索引),按照属性创建顺序...

也就是说,您可以依靠这样的事实,即对象属性始终按插入顺序进行迭代(除非您使用delete ,有关详细信息,请参见此处 )。

因此,要对某个对象中的键进行排序,只需创建一个新对象,然后按排序顺序向其添加键:

 function sortKeys(x) { if (typeof x !== 'object' || !x) return x; if (Array.isArray(x)) return x.map(sortKeys); return Object.keys(x).sort().reduce((o, k) => ({...o, [k]: sortKeys(x[k])}), {}); } //// obj = { "username": "jdoe@mail.com", "sTime": "2016-03-04T13:53:37Z", "function": "begin", "functionParams": { "tip": "ABC123FFG", "pad": 4, "passenger": [{ "firstName": "John", "phone": 1234567890, "email": "jdoe@mail.com", "dateOfBirth": "1915-10-02T00:00:00Z", "bans": { "weight": 9, "count": 2 } } ] }, "salt": "00d878f5e203", "pep": "sdeODQ0T" } sorted = sortKeys(obj); console.log(sorted); 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM