0

我有一组简单的 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
        }
    ]

}
}

我将如何解决这个问题?简单地循环遍历并命名对象并没有让我走到任何地方。

4

2 回答 2

2

作为对 TJ Crowder 建议的补充:相同的基本原理,只是不依赖 ES5 函数,也不需要 shim。注意:此解决方案在一个方面确实与您的“所需输出”不同:我没有让每个类别引用一个只有 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.bounceresult但更重要的是,首先不需要该属性:

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}
 }
于 2013-05-06T22:03:37.557 回答
0

简单地循环遍历并命名对象并没有让我走到任何地方。

然而,这正是您需要做的。:-) 可能将它们写入不同的对象。

例如:现场示例| 来源

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

这只是它的骨头,你需要做一些你总结反弹等的事情。但这应该让你开始......

以上依赖于 ES5forEach功能。如果您需要支持没有它的浏览器,您可以应用“ES5 shim”。

于 2013-05-06T21:54:48.287 回答