为标题中缺少信息道歉,我无法用更好的方式来描述我的问题。
我目前正在构建一个简单的脚本,用于从其他网站上抓取数据,并最终在自定义获取的数据后,
输出结果为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"
}
}
}]
}
答案 0 :(得分:2)
你可以这样做(从ES2015开始,也就是ES6),但请注意JSON文本中的属性顺序并不重要; JSON解析器不需要以任何特定顺序处理属性。从JSON角度看,{"a":1,"b":2}
和{"b":2,"a":1}
相同。因此,您可以按照您所描述的顺序生成具有属性的JSON,但这并不意味着它将按照该顺序消费。
因此,对于大多数用例,它不值得做。
对于值得做的用例(例如,生成可以进行文本比较的JSON文本,例如在源代码管理系统中),可以从ES2015开始执行,因为在ES2015引入了具有订单的对象属性的概念。 "拥有"的详细信息抽象OrdinaryOwnPropertyKeys
operation涵盖了对象的属性,它表示看起来像数组索引的属性首先按数字顺序排列,然后是属性创建顺序中的字符串的任何其他属性名称,后跟属性名称,即属性创建顺序中的符号。
这意味着如果我们按照该顺序在对象上创建LW
,C
和RW
属性,那么尊重属性顺序的操作将会处理他们按顺序。
那么问题是:JSON.stringify
是否尊重财产秩序?并非所有操作都可以。 (值得注意的是:for-in
和Object.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;
}
...但你可能会更优雅的东西。 (啊,看起来像Nina already did。)
但是当JSON被消耗时会发生什么?
如果另一端是JavaScript端点,并且也符合ES2015,则值得注意JSON.parse
以文本顺序在对象上创建属性,因此将保持顺序。但同样,JSON没有规定这一点,因此处理JSON的任何其他事情都可以做到它所喜欢的。
答案 1 :(得分:0)
此提案假设public boolean addItem(String name, int quantity,double price){
if(quantity <= 0){
System.out.println("Item wasnt added");
return false;}
else{
item [nItem++];//here is the problem
}
}
是一个对象,而不是数组,因为属性。
你可以引入一个带边的数组
forwards
并将代码更改为
sides = ['LW', 'C', 'RW'];
答案 2 :(得分:-1)
你可以这样做:
var input = [
{
"line": {
"forwards": [
"Player 1",
"Player 2",
"Player 3"
]
}
},
{
"line": {
"forwards": [
"Player 4",
"Player 5",
"Player 6"
]
}
},
// ...
// In total of 4 lines
];
var output = input.map(function (element) {
var _forwards = {};
element.line.forwards.forEach(function (name, key) {
var keymap = ['LW','C','RW'];
_forwards[keymap[key]]=name;
});
element.line.forwards = _forwards;
return element;
});