2

We have a JSON file:

var response = {
  "Status": "Met",
  "Text": "Text1",
  "Id": "AAA",
  "ContentItems": [
    {
      "Selected": true,
      "Text": "Text2",
      "Id": "BBB"
    },
    {
      "Status": "Met",
      "Text": "Text3",
      "Id": "CCC",          
      "ContentItems": [
        {
          "Selected": true,
          "Text": "Text5",
          "Id": "DDD"
        },
        {
          "Status": "Met",
          "Text": "Text6",
          "Id": "EEE",
          "ContentItems": [
            {
              "Selected": true,
              "Text": "Text7",
              "Id": "FFF"
            },
            {
              "Selected": true,
              "Text": "Text8",
              "Id": "GGG"
            },
            {
              "Status": "Met",
              "Text": "Text9",
              "Id": "III",
              "ContentItems": [
                {
                  "Status": "Met",
                  "Text": "Text11",
                  "Id": "JJJ",
                  "ContentItems": [
                    {
                      "Text": "Text12",
                      "Id": "77"
                    },
                    {
                      "Status": "Met",
                      "Text": "Text13",
                      "Id": "10",
                      "ContentItems": [
                        {
                          "Text": "Text14",
                          "Id": "45"
                        },
                        {
                          "Selected": true,
                          "Text": "Text15",
                          "Id": "87"
                        },
                        {
                          "Selected": true,
                          "Text": "Text16",
                          "Id": "80"
                        }
                      ]
                    }                            
                  ]
                },
                {
                  "Status": "Met",
                  "Text": "Text17",
                  "Id": "KKK",
                  "ContentItems": [
                    {
                      "Text": "Text18",
                      "Id": "12"
                    },
                    {
                      "Status": "NotMet",
                      "Text": "Text19",
                      "Id": "14",
                      "ContentItems": [
                        {
                          "Text": "Text20",
                          "Id": "55"
                        },
                        {
                          "Selected": true,
                          "Text": "Text21",
                          "Id": "98"
                        }
                      ]
                    }                            
                  ]
                }
              ]
            }
          ]
        }
      ]
    }
  ]
};

From the JSON file we need the following:

1.Return true if all "Status" is "Met".

2.Return false if any "Status" is "NotMet".

Since Child nodes can be any level deep; I used recursion function to traverse to each node and from there i'm looping over the child nodes and recursively calling the function.

I tried this code but its not working as expected.

function isStatusMet(response) {
  if (response.Status == 'NotMet') {
    return false;
  } else {
    if (response.ContentItems) {
      if(Array.isArray(response.ContentItems)) {
        for(var i = 0; i < response.ContentItems.length;i++) {
          if (response.ContentItems[i].ContentItems) {
            return isStatusMet(response.ContentItems[i]);
          } else {
            if (response.ContentItems[i].Status == 'NotMet') {
              return false;
            } else {
              continue;
            }
          }
        }
        return true;
      }
    } 
  }
}
Jsm J
  • 23
  • 3
  • Possible duplicate of [Access / process (nested) objects, arrays or JSON](http://stackoverflow.com/questions/11922383/access-process-nested-objects-arrays-or-json) – Teemu Feb 03 '17 at 11:00
  • If you return from inside a for-loop, all the next interations in that loop are skipped, so your code only checks the first child of each node. Array.every() should be very useful here. – Shilly Feb 03 '17 at 11:02
  • If you are already using jQuery, this might be useful for any property you want: http://kapilkashyap.github.io/jquery-filter-json-plugin/ Paste the above JSON in the textarea of the demo and change the property input field to have Status as the property (case sensitve). Leave the Avoid duplicates checkbox ticked and click on Filter JSON button to give you the result. – Kapil Kashyap Feb 03 '17 at 12:57

3 Answers3

1

The statement return isStatusMet(response.ContentItems[i]); will do a premature exit on any status. It should only return false if the recursive call answers false, or else the loop needs to continue.

Change it to this:

if (response.ContentItems[i].ContentItems) {
    if (!isStatusMet(response.ContentItems[i])) return false;
}
Peter B
  • 22,460
  • 5
  • 32
  • 69
1

You could use Array#every and use it recursive if ContentItems is an array.

var data = { Status: "Met", Text: "Text1", Id: "AAA", ContentItems: [{ Selected: true, Text: "Text2", Id: "BBB" }, { Status: "Met", Text: "Text3", Id: "CCC", ContentItems: [{ Selected: true, Text: "Text5", Id: "DDD" }, { Status: "Met", Text: "Text6", Id: "EEE", ContentItems: [{ Selected: true, Text: "Text7", Id: "FFF" }, { Selected: true, Text: "Text8", Id: "GGG" }, { Status: "Met", Text: "Text9", Id: "III", ContentItems: [{ Status: "Met", Text: "Text11", Id: "JJJ", ContentItems: [{ Text: "Text12", Id: 77 }, { Status: "Met", Text: "Text13", Id: 10, ContentItems: [{ Text: "Text14", Id: 45 }, { Selected: true, Text: "Text15", Id: 87 }, { Selected: true, Text: "Text16", Id: 80 }] }] }, { Status: "Met", Text: "Text17", Id: "KKK", ContentItems: [{ Text: "Text18", Id: 12 }, { Status: "NotMet", Text: "Text19", Id: 14, ContentItems: [{ Text: "Text20", Id: 55 }, { Selected: true, Text: "Text21", Id: 98 }] }] }] }] }] }] },
    result = [data].every(function iter(a) {
        return a.Status !== 'NotMet' && (!Array.isArray(a.ContentItems) || a.ContentItems.every(iter));
    });

console.log(result);
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
1
var isStatusMet = function isStatusMet( data ) {
    // If the status is NotMet, we finish immediately
    if (data.Status === 'NotMet') return false;
    // Since only nodes with ContentItems have a status, we check if the node has children and recursively check if every child has no Status of NotMet
    else if (data.hasOwnProperty('ContentItems')) return data.ContentItems.every(isStatusMet);
    // We're dealing with a child without Status or Childnodes, so we just return true.
    // Since the status in not met and the parent node of this node expects in its 'every' loop that we only return false for nodes that have Status NotMet, this makes the recusion work.
    else return true;
};

var met = isStatusMet(response);

console.log(met);
Shilly
  • 8,511
  • 1
  • 18
  • 24