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
    }
]
}

これが出力される方法の問題は、データが利用できるかどうかに依存し、番号でオブジェクトにアクセスすると、予期しない機能が作成される可能性があることです。2 つ目の問題は、javascript で操作する必要があり、サーバー側で操作できないことです。

各カテゴリがオブジェクト (現在は 3 つですが、最大 5 つになる可能性があります) がオブジェクト内のデータを要約するように、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 関数に依存せず、シムも必要としない、同じ基本原則。注:このソリューションは、 「目的の出力」とは 1 つの点で異なります。各カテゴリに 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}
 }
于 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);
});

それは骨組みにすぎません。バウンスなどを合計する部分を少し行う必要があります。しかし、それで始められるはずです...

forEach上記はES5関数に依存しています。サポートしていないブラウザーをサポートする必要がある場合は、「ES5 shim」を適用できます。

于 2013-05-06T21:54:48.287 に答える