JavaScript - 根据一定的逻辑命名对象属性

标签 javascript jquery json express cheerio

对于标题中缺乏信息表示歉意,我无法想出更好的标题来描述我的问题。

我目前正在构建一个简单的脚本,从另一个网站抓取数据,最终在自定义获取的数据后, 将结果输出为 JSON

代码没有任何“错误”或“损坏”,我也没有收到任何错误,只需要稍微改进我的脚本。

下面是我用 Express 编写的脚本,用于获取其他网站的玩家:

router.get('/teams/:id/roster', function(req, res) {

var id = req.params.id;

var url = 'http://www.testdata.dev/api/teams/' + id;

request(url, function (error, response, html) {
    if (!error && response.statusCode == 200) {
        var $ = cheerio.load(html); // load the DOM with Cheerio

        $('#roster').filter(function () {
            var player, line, lines = [], forward = {}, defense = {};
            line = {
                "forwards": forward
            };

            // Iterate over all the forwards
            $("#forwards > tbody > tr > td").each(function(index) {

                var that = $(this);
                player = that.text().trim(); // F.e "Lebron James", "Michael Jordan"

                // Create a new line after every three players (in total of 12 forwards, in total of 4 lines)
                if(index % 3 == 0) {

                    lines.push({
                        "line": {
                            "forwards": [player]
                        }
                    });
                } else {
                    lines[lines.length - 1]["line"]["forwards"].push(player);
                }
            });

            // Output results as JSON
            res.contentType('application/json');
            res.json(lines);
        });
    } else {

        console.log("Request was not made");

    }
});

});

当前 JSON 输出:

[
  {
    "line": {
      "forwards": [
        "Player 1",
        "Player 2",
        "Player 3"
      ]
    }
  },
  {
    "line": {
      "forwards": [
        "Player 4",
        "Player 5",
        "Player 6"
      ]
    }
  },
 // ...
 // In total of 4 lines
]

所以代码完成了它的工作,我能够输出 JSON ,如上所述。但是,我想根据以下规则集为每个球员提供一个属性:每个“线”对象中输出的第一个球员将始终是 LW(左翼),第二个球员将始终是 C(中锋)并且第三位 RW(右翼)。

不幸的是,我无法自己实现这一点,这就是我需要你的帮助的地方。提前致谢!

预期 JSON 输出:

{
    "lines": [{
        "line": {
            "forwards": {
                "LW": "Player 1",
                "C": "Player 2",
                "RW": "Player 3"
            }
        }
    }, {
        "line": {
            "forwards": {
                "LW": "Player 1",
                "C": "Player 2",
                "RW": "Player 3"
            }
        }
    }]
}

最佳答案

可以执行此操作(从 ES2015 开始,又名 ES6),但请注意,JSON 文本中的属性顺序并不重要; JSON 解析器不需要以任何特定顺序处理属性。 {"a":1,"b":2}{"b":2,"a":1} 相同从 JSON 的 Angular 来看。因此,您可以按照您所描述的顺序生成具有属性的 JSON,但这并不意味着它将按该顺序使用

因此对于大多数用例来说,这是不值得做的。

对于值得做的用例(例如,生成可以进行文本比较的 JSON 文本,例如在源代码控制系统中),您可以从 ES2015 开始这样做,因为在ES2015,引入了对象属性具有顺序的概念。摘要 OrdinaryOwnPropertyKeys operation 涵盖了对象“自己”属性的详细信息。 ,它表示看起来像数组索引的属性按数字顺序排在前面,然后是按属性创建顺序排列的任何其他字符串属性名称,最后是按属性创建顺序排列的符号属性名称。

这意味着如果我们按顺序在对象上创建 LWCRW 属性 ,那么尊重属性顺序的操作将按该顺序处理它们。

那么问题是:JSON.stringify 是否尊重属性顺序?并非所有操作都如此。 (值得注意的是:for-inObject.keys 不是必需的。)

不过,答案是,确实如此。对于普通对象,JSON.stringify 使用抽象 SerializeJSONObject操作,它使用抽象 EnumerableOwnNames操作,它使用 [[OwnPropertyKeys]],对于普通对象,它使用我上面提到的 OrdinaryOwnPropertyKeys 操作。

因此,这意味着在符合 ES2015 的实现中,JSON.stringify({a:1,b:2}) 必须为 '{"a":1,"b": 2}'JSON.stringify({b:2,a:1}) 必须为 '{"b":2,"a":1}' (因为对象初始值设定项按源代码顺序创建其属性)。

所以结果是:如果为每一行创建 forwards 对象:

forwards = {};

...并按照当前将 LW、C 和 RW 属性添加到数组的顺序添加它们,使用 JSON.stringify 的兼容实现将输出 JSON按此顺序排列。

如何按顺序添加它们是实现的问题。一个真正最小的、简单的、未经优化的方法是替换

lines[lines.length - 1]["line"]["forwards"].push(player);

var f = lines[lines.length - 1]["line"]["forwards"];
if (!f.LW) {
    f.LW = player;
} else if (!f.C) {
    f.C = player;
} else {
    f.RW = player;
}

...但是你可能可以用更优雅的东西来 p。 (啊,看起来像Nina already did。)

但是当 JSON 被使用时会发生什么?

如果另一端是 JavaScript 端点,并且也兼容 ES2015,则值得注意的是 JSON.parse 按文本顺序在对象上创建属性,因此将保持顺序。但同样,JSON 并没有规定这一点,因此任何其他处理 JSON 的东西都可以做它想做的事。

关于JavaScript - 根据一定的逻辑命名对象属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41446401/

相关文章:

javascript - 在Javascript中减去UTC格式的日期时间

javascript - 两页,一个 jQuery 脚本,一个站点出现错误

javascript - 如何在更新/不警告框上从下弹出消息窗口

javascript - 如何在ajax函数调用中发送var来发送POST?

javascript - 使用递归函数遍历 JSON 字符串到内部级别

javascript json 数据脚本无法工作

javascript - RabbitMQ 消费者应该通过路由键而不是 QueueName 进行监听

javascript - 使用 ng-click 调用链接到我的项目的 JavaScript 函数

javascript - 一次只允许运行一个间隔

android - Retrofit2 指定根元素并转换数据类型