Danielok1993
Danielok1993

Reputation: 359

Looping through JSON children objects

So I am looping through mid-complex json object and saving all the values when I reach the end of recursive loop

Object e.g.

"if": {
    "and": {
        "or": {
            "compare": [
                {
                    "Hello": {
                        "constant": {
                            "string": "1"
                        }
                    },
                },
                {
                    "Hello": {
                        "constant": {
                            "string": "4"
                        }
                    }
                }
            ]
        },
        "before": {
            "Hello2": "12131",
            "Hello": {
                "constant": {
                    "datetime": "2001-01-01T00:00:00"
                }
            }
        }
    }
}

Then I have my function:

function getAllGroups(obj)
{

        for (var k in obj)
        {
            if (k === "hello") {
                counter++;
                array.push([]);
            }
            if (typeof obj[k] == "object" && obj[k] !== null) {
                getAllGroups(obj[k]);
            }
            else
            {
                if (k !== "hello2") {
                    array[array.length - 1].push(obj[k]);
                }
            }

        }
}

It might make no sense right now but basically:

When it finds key "hello" I add new object to my empty array and populate that object with data. Everytime it reaches key "hello" it will create new object and populate it with new data.

So I got stuck at keeping reference to the parent object. There are few keys that I want to maintain e.g. "and" & "or". Therefore I have first end of loop which stops at string: 1 I want to maintain that it is part of "or". Similarly, I want to keep that "or" is part of "and". Lastly that datetime is part of "and". Keep in mind that I can have multiple "and" and "or" within each other.

EDIT:

I have changed to code so that it will keep the reference to the parent. Unfortunately it will keep reference to the last parent in the list, therefore "datetime" is child of "and", but my code shows its child of "or"

function getAllGroups(obj)
{

        for (var k in obj)
        {
            if (k === "and" || k === "or" || k === "not")
            {
                if (parentKey !== "") {
                    array.push([]);
                    array[array.length - 1].push(array[array.length - 1]['parent'] = parentKey);
                    parentKey = k + parentKeyNo;
                    parentKeyNo++;
                    array[array.length - 1].push(array[array.length - 1]['child'] = parentKey);
                }
                else {
                    parentKey = k + parentKeyNo;
                    parentKeyNo++;
                    array.push([]);
                    array[array.length - 1].push(array[array.length - 1]['child'] = parentKey);
                }
            }
            if (k === "Hello") {
                counter++;
                array.push([]);
            }
            if (typeof obj[k] == "object" && obj[k] !== null) {
                getAllGroups(obj[k]);
            }
            else
            {
                if (k !== "Hello2") {
                    if (array[array.length - 1].hasOwnProperty('parent'))
                    {
                        array[array.length - 1].push(obj[k]);
                    }
                    else
                    {
                        array[array.length - 1].push(array[array.length - 1]['parent'] = parentKey);
                        array[array.length - 1].push(obj[k]);
                    }

                }
            }

        }
}

DESIRED RESULT:

[
    [
        {
            "child": "and"
        }
    ],
    [
        {
            "parent": "and"
        },
        {
            "child": "or"
        }
    ],
    [
        {
            "parent": "or"
        },
        {
            "string": "1"
        }
    ],
    [
        {
            "parent": "or"
        },
        {
            "string": "4"
        }
    ],
    [
        {
            "parent": "and"
        },
        {
            "datetime": "2001-01-01T00:00:00"
        }
    ]
]

Upvotes: 2

Views: 3895

Answers (1)

hungndv
hungndv

Reputation: 2141

Here you are, you handle your key and value in process() function:

var json = {
  "if": {
    "and": {
      "or": {
        "compare": [{
          "Hello": {
            "constant": {
              "string": "1"
            }
          },
        }, {
          "Hello": {
            "constant": {
              "string": "4"
            }
          }
        }]
      },
      "before": {
        "Hello": {
          "constant": {
            "datetime": "2001-01-01T00:00:00"
          }
        }
      }
    }
  }
};

//called with every property and it's value
var helloValues = [];

function process(key, value) {
  console.log(key + " : " + value);
  if (key == 'Hello') helloValues.push(value);
}

function traverse(o, func) {
  for (var i in o) {
    func.apply(this, [i, o[i]]);
    if (o[i] !== null && typeof(o[i]) == "object") {
      //going on step down in the object tree!!
      traverse(o[i], func);
    }
  }
}

//that's all... no magic, no bloated framework
traverse(json, process);
alert(helloValues.length);

Hope this helps.

Upvotes: 2

Related Questions