在jQuery中使用动态对象名重新格式化JSON

时间:2013-05-06 21:51:31

标签: javascript jquery json dynamicobject

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

}
}

我该如何解决这个问题?简单地循环并命名对象让我无处可去。

2 个答案:

答案 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垫片”。