我有一组简单的JSON需要重新格式化,因为并不总是输出所有键值对。
{
"result": [
{
"category": "Negative Notification",
"event": "open",
"result": 2
},
{
"category": "Referral",
"event": "bounce",
"result": 1
},
{
"category": "Negative Notification",
"event": "delivered",
"result": 34
},
{
"category": "Negative Notification",
"event": "processed",
"result": 34
},
{
"category": "Positive Notification",
"event": "open",
"result": 42
},
{
"category": "Referral",
"event": "delivered",
"result": 17
},
{
"category": "Positive Notification",
"event": "processed",
"result": 504
},
{
"category": "Referral",
"event": "processed",
"result": 18
},
{
"category": "Positive Notification",
"event": "delivered",
"result": 504
},
{
"category": "Negative Notification",
"event": "bounce",
"result": 16
},
{
"category": "Positive Notification",
"event": "bounce",
"result": 176
},
{
"category": "Referral",
"event": "open",
"result": 10
}
]
}
输出方式的问题取决于数据是否可用的天气,按编号访问对象可能会产生意外的功能。第二个问题是必须由javascript操纵,并且不能在服务器端进行操作。
我希望重新格式化JSON,以便每个类别都是一个对象(目前有三个,但可能多达五个)已在对象内部汇总了数据。例如:
{
"result": {
"Negative Notification" : [
{
"processed":34,
"delivered":34,
"bounces":16,
"opens":2
}
],
"Positive Notification" : [
{
"processed":504,
"delivered":504,
"bounces":176,
"opens":42
}
],
"Referral" : [
{
"processed":18,
"delivered":17,
"bounces":1,
"opens":10
}
]
}
}
我该如何解决这个问题?简单地循环并命名对象让我无处可去。
答案 0 :(得分:2)
作为T.J Crowder建议的补充:同样的基本原则,只是不依赖于ES5功能,也不需要垫片。 注意:此解决方案与您的“所需输出”的区别在于:不是让每个类别引用一个只有1个元素(对象文字)的数组,只是直接为它指定一个对象文字。您需要的格式要求您访问退回的推荐内容,例如obj.result.Referral[0].bounces
,而我认为如果它是obj.result.Referral.bounces
则更有意义,而不介于其间。
//suppose a is the raw JSON data
var b = {result:{}};//this will become be the object you want
for (var i=0;i<a.result.length;i++)
{
b.result[a.result[i].category] = (function(obj)
{
var p, res = {};
for (p in obj)
{
if (p !== 'category' && obj.hasOwnProperty(p))
{
res[p] = obj[p];
}
}
return res;
}(a.result[i]));
}
这会循环遍历由a.result
引用的数组,每次使用a.result[i].category
的值作为保存其他数据的对象的属性名称。
结果是:
console.log(JSON.stringify(b));
{"result":
{"Negative Notification":
{"event":"bounce",
"result":16},
"Referral":
{"event":"open",
"result":10},
"Positive Notification":
{"event":"bounce","result":176}
}
}
但实际上:为什么不在发送之前格式化数据,如果您有权访问输出此数据的代码,请更改该代码以更好地满足您的需求。
编辑:
在回应你的评论时,我认为你真正追求的是:
var b={result{}};
for (i=0;i<a.result.length;i++)
{
b.result[a.result[i].category] = b.result[a.result[i].category] || {};//use existing, or create new object
b.result[a.result[i].category][a.result[i].event] = a.result[i].result;//add property for event type, assign value
}
此代码运行后,对象b
如下所示:
{"result":
{"Negative Notification":
{"open":2,
"delivered":34,
"processed":34,
"bounce":16},
"Referral":
{"bounce":1,
"delivered":17,
"processed":18,
"open":10},
"Positive Notification":
{"open":42,
"processed":504,
"delivered":504,
"bounce":176}
}
}
这意味着,您可以使用b.result.Referral[0].bounce
,而不是使用b.result.Referral.bounce
。但更重要的是,首先不需要result
属性:
var result ={};
for (i=0;i<a.result.length;i++)
{
result[a.result[i].category] = result[a.result[i].category] || {};
result[a.result[i].category][a.result[i].event] = a.result[i].result;
}
console.log(result);
{"Negative Notification":
{"open":2,
"delivered":34,
"processed":34,
"bounce":16},
"Referral":
{"bounce":1,
"delivered":17,
"processed":18,
"open":10},
"Positive Notification":
{"open":42,
"processed":504,
"delivered":504,
"bounce":176}
}
答案 1 :(得分:0)
简单地循环并命名对象让我无处可去。
但是,这正是你需要做的。 :-)可能将它们写入不同的对象。
例如:Live Example | Source
// The object that will contain the result
var obj = {};
// Loop through the `result` array on your object
yourObject.result.forEach(function(element) {
// See if we already have an entry for that category
var entry = obj[element.category];
if (!entry) {
// We don't, so create a blank array for it
entry = obj[element.category] = [];
}
// Push this entry in the category's array
entry.push(element);
});
这只是它的骨头,你需要做一点你总结反弹等等。但这应该让你开始......
以上内容依赖于ES5 forEach
功能。如果您需要支持没有它的浏览器,您可以应用“ES5垫片”。