JS通过深度嵌套的对象对JSON进行归类和分组

时间:2019-03-04 16:32:12

标签: javascript json javascript-objects reducers

我正在通过REST提取一个JSON,其中包含带有一些字段和一些嵌套对象的对象数组。

我要创建的是嵌套JSON对象数组中的分组摘要对象,其结构如下:

 var data = [
        {
            "Id": 79,
            "Date": "2019-02-17T00:00:00-07:00",
            "StartTime": 1535385600,
            "EndTime": 1535416200,
            "Slots": [
                {
                    "blnEmptySlot": false,
                    "strType": "B",
                    "intStart": 3600,
                    "intEnd": 5400,
                    "intUnixStart": 1535389200,
                    "intUnixEnd": 1535391000,
                }
            ],
            "OperationalUnit": 3,
            "Created": "2019-01-31T11:23:29+02:00",
            "StartTimeLocalized": "2019-02-17T10:00:00+02:00",
            "EndTimeLocalized": "2019-02-17T19:00:00+02:00",
            "_MetaData": {
                "AttendeeInfo": {
                    "Id": 111,
                    "AttendeeDisplayName": "att_name1",
                    "AttendeeProfile": 406,
                    "Attendee": 406,
                    "Photo": "avatar_path"
                  },
                "OperationalUnitInfo": {
                    "Id": 3,
                    "OperationalUnitName": "op_unit_name",
                    "Company": 1,
                    "CompanyName": "comp_name",
                    "LabelWithCompany": "comp_label"
                },
            }
        },
        {
            "Id": 80,
            "Date": "2019-02-17T00:00:00-07:00",
            "StartTime": 1535385600,
            "EndTime": 1535416200,
            "Slots": [
                {
                    "blnEmptySlot": false,
                    "strType": "B",
                    "intStart": 3600,
                    "intEnd": 5400,
                    "intUnixStart": 1535389200,
                    "intUnixEnd": 1535391000,
                }
            ],
            "OperationalUnit": 3,
            "Created": "2019-01-31T11:23:29+02:00",
            "StartTimeLocalized": "2019-02-17T10:00:00+02:00",
            "EndTimeLocalized": "2019-02-17T19:00:00+02:00",
            "_MetaData": {
                "AttendeeInfo": {
                    "Id": 112,
                    "AttendeeDisplayName": "att_name2",
                    "AttendeeProfile": 407,
                    "Attendee": 407,
                    "Photo": "avatar_path"
                  },
                "OperationalUnitInfo": {
                    "Id": 3,
                    "OperationalUnitName": "op_unit_name",
                    "Company": 1,
                    "CompanyName": "comp_name",
                    "LabelWithCompany": "comp_label"
                },
            }
        }
    ];

总体目的是创建一个具有开始和结束日期时间的事件对象列表,一个LabelWithCompany字符串(深层嵌套对象)以及一个按OperationalUnitName以及开始和结束时间分组的所有与会者的列表。

示例:

[
    {
        "2019-02-17T00:00:00-08:00": {//Date
            "2019-02-17T10:00:00+02:00": {//StartTimeLocalized
                "2019-02-17T19:00:00+02:00": {//EndTimeLocalized
                    "[NYC] Network - Solutions": {//LabelWithCompany
                        "attendees": [
                            "att_name1",//AttendeeDisplayName
                            "att_name2"  //AttendeeDisplayName    
                        ]
                    }
                }
            }
        }
    }
]

我认为map和reduce是必需的功能,但是在执行多个嵌套的reduce时遇到了麻烦。 关于如何将这些对象聚合为包含每个会话的所有与会者的聚合格式的任何其他建议。

2 个答案:

答案 0 :(得分:0)

您可以使用一些辅助函数来获取嵌套对象的值,并通过获取键数组来设置路径并返回最后一个嵌套对象。

然后,您需要获取嵌套结果集的键,另一个则获取推入结果的值。

const
    getValue = (object, path) => [].concat(path).reduce((o, k) => o[k], object),
    setPath = (object, path) => [].concat(path).reduce((o, k) => o[k] = o[k] || {}, object);

var data = [{ Id: 79, Date: "2018-08-27T00:00:00-07:00", StartTime: 1535385600, EndTime: 1535416200, Slots: [{ blnEmptySlot: false, strType: "B", intStart: 3600, intEnd: 5400, intUnixStart: 1535389200, intUnixEnd: 1535391000 }], OperationalUnit: 3, Created: "2019-01-31T11:23:29+02:00", StartTimeLocalized: "2019-02-17T10:00:00+02:00", EndTimeLocalized: "2019-02-17T19:00:00+02:00", _MetaData: { AttendeeInfo: { Id: 111, AttendeeDisplayName: "att_name1", AttendeeProfile: 406, Attendee: 406, Photo: "avatar_path" }, OperationalUnitInfo: { Id: 3, OperationalUnitName: "op_unit_name", Company: 1, CompanyName: "comp_name", LabelWithCompany: "comp_label" } } }, { Id: 80, Date: "2018-08-27T00:00:00-07:00", StartTime: 1535385600, EndTime: 1535416200, Slots: [{ blnEmptySlot: false, strType: "B", intStart: 3600, intEnd: 5400, intUnixStart: 1535389200, intUnixEnd: 1535391000 }], OperationalUnit: 3, Created: "2019-01-31T11:23:29+02:00", StartTimeLocalized: "2019-02-17T10:00:00+02:00", EndTimeLocalized: "2019-02-17T19:00:00+02:00", _MetaData: { AttendeeInfo: { Id: 112, AttendeeDisplayName: "att_name2", AttendeeProfile: 407, Attendee: 407, Photo: "avatar_path" }, OperationalUnitInfo: { Id: 3, OperationalUnitName: "op_unit_name", Company: 1, CompanyName: "comp_name", LabelWithCompany: "comp_label" } } }],
    keys = ["Date", "StartTimeLocalized", "EndTimeLocalized", ["_MetaData", "OperationalUnitInfo", "LabelWithCompany"]],
    value = ["_MetaData", "AttendeeInfo", "AttendeeDisplayName"],
    result = data.reduce((r, o) => {
        var temp = setPath(r, keys.map(getValue.bind(null, o)));

        temp.attendees = temp.attendees || [];
        temp.attendees.push(getValue(o, value));
        return r;
    }, {});

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

答案 1 :(得分:0)

您可以定义一个函数来简化层次结构(drill)的创建,然后遍历记录,如下所示:

const data = [{"Id": 79,"Date": "2019-02-17T00:00:00-07:00","StartTime": 1535385600,"EndTime": 1535416200,"Slots": [{"blnEmptySlot": false,"strType": "B","intStart": 3600,"intEnd": 5400,"intUnixStart": 1535389200,"intUnixEnd": 1535391000,}],"OperationalUnit": 3,"Created": "2019-01-31T11:23:29+02:00","StartTimeLocalized": "2019-02-17T10:00:00+02:00","EndTimeLocalized": "2019-02-17T19:00:00+02:00","_MetaData": {"AttendeeInfo": {"Id": 111,"AttendeeDisplayName": "att_name1","AttendeeProfile": 406,"Attendee": 406,"Photo": "avatar_path"},"OperationalUnitInfo": {"Id": 3,"OperationalUnitName": "op_unit_name","Company": 1,"CompanyName": "comp_name","LabelWithCompany": "comp_label"},}},{"Id": 80,"Date": "2019-02-17T00:00:00-07:00","StartTime": 1535385600,"EndTime": 1535416200,"Slots": [{"blnEmptySlot": false,"strType": "B","intStart": 3600,"intEnd": 5400,"intUnixStart": 1535389200,"intUnixEnd": 1535391000,}],"OperationalUnit": 3,"Created": "2019-01-31T11:23:29+02:00","StartTimeLocalized": "2019-02-17T10:00:00+02:00","EndTimeLocalized": "2019-02-17T19:00:00+02:00","_MetaData": {"AttendeeInfo": {"Id": 112,"AttendeeDisplayName": "att_name2","AttendeeProfile": 407,"Attendee": 407,"Photo": "avatar_path"},"OperationalUnitInfo": {"Id": 3,"OperationalUnitName": "op_unit_name","Company": 1,"CompanyName": "comp_name","LabelWithCompany": "comp_label"},}}];

const drill = (o, key, ...keys) => key ? drill(o[key] = o[key] || {}, ...keys) : o; 

const result = {};    
for (const e of data) {
    const key = drill(result, e.Date, 
                              e.StartTimeLocalized, 
                              e.EndTimeLocalized, 
                              e._MetaData.OperationalUnitInfo.LabelWithCompany);
    key.attendees = (key.attendees || []).concat(
                              e._MetaData.AttendeeInfo.AttendeeDisplayName);
}

console.log(result);

注意:将输出包装在数组中似乎没有用,但是您当然可以这样做。