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

标签 javascript python sorting recursion

我试图获得与启用按键排序的 pythons json.dumps() 相同的结果。这是作为 Postman 的预请求脚本来生成请求哈希值的。输出需要对有效的 json 进行排序,该 json 用作哈希的输入。我是 javascript 的新手,看到许多旧答案声称 javascript 中的对象无法排序。然而,必须有一个解决方案来生成给定标准的哈希值。

  • 对象结构无法更改。
  • 它只需要支持 Chrome。
  • 我可以使用库。
  • requestParams 可以包含需要以任意深度排序的嵌套对象和数组。

这是我当前的代码。在 Chrome 控制台中,sortedResult 的对象预览是未排序的,但是当我展开对象和子对象时,Chrome 控制台将排序结果显示为已排序,这正是它应该的方式。这给我的印象是 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 states 表示

Although ECMAScript makes iteration order of objects implementation-dependent, it may appear that all major browsers support an iteration order based on the earliest added property coming first (at least for properties not on the prototype).

ES2015 makes this behaviour standard:

For each own property key P of O that is a String but is not an integer index, in property creation order...

也就是说,您可以相信对象属性始终按插入顺序迭代(除非您使用delete,请参阅 here 了解详细信息)。

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

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);

关于Javascript 递归地排序对象和嵌套对象以及数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35811799/

相关文章:

javascript - 移动设备隐式流上的静默刷新 token

javascript - Sequelize findOne include 给出空数组

python - 是否可以构建具有邻接矩阵的图?

python - 如何使用 django_filters.DateFilter?

python - Django/Python 不可排序类型 Story() < Story() with sorting function

c++ - 能否在 O(n) 中识别和量化字符串中的重复字符?

时间格式的 JavaScript 正则表达式验证问题

javascript - 使用javascript单击按钮后如何禁用特定表格行中的复选框?

python - 从Python中的字符串中删除html标签和实体

python - 为相同的字典值创建可交换元组键的最佳方法是什么?