Loop Through Object Searching For Property And Modify Original Object on Success

南楼画角 提交于 2019-12-10 10:15:03

问题


var myObj = 
    data: {
    {
    chairId: "CHAIRCHROME009",    
    relatedOrders: [
        {
            someProp: 45423234,
            data : {
                firstOrder: {},
                relatedOrders: [
                    {
                        someProp: 5757587,
                        data : {
                            firstOrder: {},
                            relatedOrders: [ ],
                            notifications: [
                                {
                                    notificationId: "CHAIR-0909FF",
                                    latestNotification: {                                
                                        latestNotificationAction: "New",
                                        priority: "High",                                
                                    }
                                }
                            ],
                            relations: [ ]
                        }
                    }
                ],
                relations: [ ]
            }
        }
    ],
    relations: [ ]
}
}

How can i endlessly loop through an object containing arrays and objects, essentially searching for a notifications property.

In the example above, notifications is 2 levels deep in to myObj, however it could be 1 level or 100 levels. notifications will always be found under relatedOrders I then need to determine the value of notifications.latestNotification.latestNotificationAction

If no notifications are found, null or false should be returned.

I have tried:

function isThereRelatedOrders(myObj) {
    for(var k in myObj) {
        var v = myObj[k];

        if (k === "relatedOrders") {                
            isThereData(v[0]);
        }
    }
}

function isThereData(relatedOrder) {
    for(var y in relatedOrder) {
        var t = relatedOrder[y];

        if (y === "data") {                
            isThereNotification(t);
        }
    }
}

function isThereNotification(t) {
    for(var x in t) {            
        var j = t[x];

        if (x === "notifications") {
            console.lig('notifications found');
            if(j[0].latestNotification.latestNotificationAction  === "New") {                
                console.log('is new alert');
                // Add a property to my original myObj root level of alert: new
            }
            else {                
                console.log('is old alert');
                // Add a property to my original myObj root level of alert: old
            }
        }
        else if(x === "relatedOrders") {
            alert('SUB relatedOrders found');
            isThereRelatedOrders(j[0]);
        }
        else {
            alert('no notifications found');
        }
    }
}

isThereRelatedOrders(myObj);

With the above, once my code has got to calling isThereRelatedOrders() for the second time, it never hits the if statement.. I guess its becuase is now need to look for .data??

With the above executed, i would want something like this to be retunred:

var myObj = {
    chairId: "CHAIRCHROME009",
    alert: "New"
    ////////

回答1:


This proposal uses an iterative and recursive approach to get the wanted property notifications and their content. If one found, the content is pushed into the result array. If nothing is found, then the array remains empty.

function iter(o) {
    if (Array.isArray(o)) {
        o.forEach(iter);
        return;
    }
    if (typeof o === 'object') {
        Object.keys(o).forEach(function (k) {
            if (k === 'chairId') {
                chairId = o[k];
            }
            if (k === 'notifications') {
                o[k].forEach(function (a) {
                    if ('latestNotificationAction' in a.latestNotification) {
                        result.push({
                            chairId: chairId,
                            alert: a.latestNotification.latestNotificationAction
                        });
                    }
                });
            }
            iter(o[k]);
        });
    }
}

var myObj = { data: { chairId: "CHAIRCHROME009", relatedOrders: [{ someProp: 45423234, data: { firstOrder: {}, relatedOrders: [{ someProp: 5757587, data: { firstOrder: {}, relatedOrders: [], notifications: [{ notificationId: "CHAIR-0909FF", latestNotification: { latestNotificationAction: "New", priority: "High", } }], relations: [] } }], relations: [] } }], relations: [] } },
    chairId,
    result = [];

iter(myObj);
document.write('<pre>' + JSON.stringify(result, 0, 4) + '</pre>');

Edit:

A solution which respects the toggle between data and relatedOrders properties.

function iter(o, flip) {
    if (Array.isArray(o)) {
        o.forEach(function (a) {
            iter(a, flip);
        });
        return;
    }
    if (typeof o === 'object') {
        if ('chairId' in o) {
            chairId = o.chairId;
        }
        if (
            flip === 'relatedOrders' &&
            'notifications' in o &&
            0 in o.notifications &&
            'latestNotification' in o.notifications[0] &&
            'latestNotificationAction' in o.notifications[0].latestNotification
        ) {
            result.push({
                chairId: chairId,
                alert: o.notifications[0].latestNotification.latestNotificationAction
            });
            return;
        }
        flip in o && iter(o[flip], flipFlop[flip]);
    }
}

var myObj = { data: { chairId: "CHAIRCHROME009", relatedOrders: [{ someProp: 45423234, data: { firstOrder: {}, relatedOrders: [{ someProp: 5757587, data: { firstOrder: {}, relatedOrders: [], notifications: [{ notificationId: "CHAIR-0909FF", latestNotification: { latestNotificationAction: "New", priority: "High", } }], relations: [] } }], relations: [] } }], relations: [] } },
    chairId,
    result = [],
    flipFlop = { relatedOrders: 'data', data: 'relatedOrders' };

iter(myObj, 'data');
document.write('<pre>' + JSON.stringify(result, 0, 4) + '</pre>');



回答2:


Here's my attempt, using your data, but cleaned up to be valid... Click on the "Run code snippet" button to run it.

var myObj = {
  data: {
    chairId: "CHAIRCHROME009",
    relatedOrders: [{
      someProp: 45423234,
      data: {
        firstOrder: {},
        relatedOrders: [{
          someProp: 5757587,
          data: {
            firstOrder: {},
            relatedOrders: [],
            notifications: [{
              notificationId: "CHAIR-0909FF",
              latestNotification: {
                latestNotificationAction: "New",
                priority: "High",
              }
            }],
            relations: []
          }
        }],
        relations: []
      }
    }],
    relations: []
  }
};

function findAllNotifications(obj, chairId) {
  var result = [];
  Object.keys(obj).forEach(function(prop) {
    if (prop === 'chairId') {
      chairId = obj.chairId;
    }
    if (prop === 'notifications') {
      obj.notifications.forEach(function(notif) {
        result.push({
          chairId: chairId,
          alert: notif.latestNotification.latestNotificationAction
        });
      });
    }
    switch (typeof obj[prop]) {
      case 'object':
        result = result.concat(findAllNotifications(obj[prop], chairId));
        break;
      case 'array':
        obj[prop].forEach(function(sub) {
          result = result.concat(findAllNotifications(sub, chairId));
        });
        break;
    }
  });
  return result;
}

var result = findAllNotifications(myObj);
console.log("Result:", result);

// Doing this so you can see the result on the web page...
document.body.appendChild(document.createTextNode(JSON.stringify(result)));

// To "reassign" to the original object:
// myObj= findAllNotifications(myObj);



回答3:


JSONPath is a perfect match for such tasks. It is very flexible and makes a lot of fun. 😀
You can download an actual fork here: https://github.com/s3u/JSONPath

1. simple task, simple solution:

If there is only one chair in your data, you could easily get the chairId and let JSONPath do the rest:

var result = {
    chairId: myObj.data.chairId,
    alert: JSONPath({json: myObj, wrap: false, path: '$..latestNotificationAction'}) || false
};
var resultString = JSON.stringify(result, 0, 4);
document.write('<pre>' + resultString + '</pre>');
<script src="https://raw.githack.com/s3u/JSONPath/master/lib/jsonpath.js"></script>
<script>
var myObj = {
    data: {
        chairId: "CHAIRCHROME009",
        relatedOrders: [{
            someProp: 45423234,
            data: {
                firstOrder: {},
                relatedOrders: [{
                    someProp: 5757587,
                    data: {
                        firstOrder: {},
                        relatedOrders: [],
                        notifications: [{
                            notificationId: "CHAIR-0909FF",
                            latestNotification: {
                                latestNotificationAction: "New",
                                priority: "High",
                            }
                        }],
                        relations: []
                    }
                }],
                relations: []
            }
        }],
        relations: []
    }
};
</script>

2. complex task, simple solution:

If your data is more complex, you can use a callback function, which will be called every time a chair with a latestNotification is found:

function find(obj, foundCallBack) {

  JSONPath({
      json: obj, resultType: 'parent', wrap: false, 
      path: '$..chairId', 
      callback: function(chair) {
          JSONPath({
              json: chair, resultType: 'parent', wrap: false, 
              path: '$..latestNotification', 
              callback: function(notification) {foundCallBack({
                  chairId: chair.chairId,
                  alert: notification.latestNotification.latestNotificationAction,
                  priority: notification.latestNotification.priority
              })}});
      }});
}
find(myObj, function(result){
   var resultString = JSON.stringify(result, 0, 4);
   alert(resultString);
   document.write('<pre>' + resultString + '</pre>');
});
<script src="https://raw.githack.com/s3u/JSONPath/master/lib/jsonpath.js"></script>
<script>
var myObj = {
    data: {
        employees: [1, 2, 3, 4],
        chairs: [
            {
                chairId: "CHAIRCHROME009",
                relatedOrders: [{
                    someProp: 45423234,
                    data: {
                        firstOrder: {},
                        relatedOrders: [{
                            someProp: 5757587,
                            data: {
                                firstOrder: {},
                                relatedOrders: [],
                                notifications: [{
                                    notificationId: "CHAIR-0909FF",
                                    latestNotification: {
                                        latestNotificationAction: "New1",
                                        priority: "High",
                                    }
                                },
                                    {
                                        notificationId: "CHAIR-0909FF",
                                        latestNotification: {
                                            latestNotificationAction: "New2",
                                            priority: "Medium",
                                        }
                                    }],
                                relations: []
                            }
                        }],
                        relations: []
                    }
                }],
                relations: []
            },
            {
                chairId: "CHAIRCHROME0077",
                relatedOrders: [{
                    someProp: 45423234,
                    data: {
                        firstOrder: {},
                        relatedOrders: [{
                            someProp: 5757587,
                            data: {
                                firstOrder: {},
                                relatedOrders: [],
                                notifications: [{
                                    notificationId: "CHAIR-090922FF",
                                    latestNotification: {
                                        latestNotificationAction: "New3",
                                        priority: "Low",
                                    }
                                }],
                                relations: []
                            }
                        }],
                        relations: []
                    }
                }],
                relations: []
            }
        ]
    }
};
</script>


来源:https://stackoverflow.com/questions/36087992/loop-through-object-searching-for-property-and-modify-original-object-on-success

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!