3

Suppose I have this object:

{CONN_INFO: {CFGSwitch: {412: {}}}}

It has a depth of 4. I want to reassign the key 412 to "{}" such that the final object would be

{CONN_INFO: {CFGSwitch: {412: "{}"}}}

Function for checking depth:

function checkDepth(object) {
  var level = 1;
  var key;
  for(key in object) {
      if (!object.hasOwnProperty(key)) continue;

      if(typeof object[key] == 'object'){
          var depth = checkDepth(object[key]) + 1;
          level = Math.max(depth, level);
      }
  }
  return level;
}

I have something like this but I'm not sure if it's optimal or will work for all cases. Would appreciate any input.

function checkIfLastLevelEmpty(obj, depth) {
  for (var key in obj) {
    var val = obj[key];
    if (Object.keys(obj[key]).length === 0) {
      obj[key] = "{}";
    }
    else {
      if (depth >0) {
        checkIfLastLevelEmpty(val, depth-1);
      }
    }
  }
}
tchan
  • 751
  • 7
  • 19
  • Maybe this can help to you http://stackoverflow.com/questions/13523951/how-to-check-the-depth-of-an-object – b2ok May 08 '17 at 14:59
  • In your checkIfLastLevelEmpty function, what is the purpose of the `depth` variable, is it to provide a maximum depth limit? – Tom 'Blue' Piddock May 08 '17 at 15:02
  • @Blue yes, I'm not too experienced with recursive functions but I'm using the depth variable as an exit if it hits depth 0 and there's no empty object. I've updated my current code to the original question. – tchan May 09 '17 at 03:25
  • That's absolutely fine man, it's a good precaution to add to recursion in-case of StackOverflowExceptions. I would call it "maxDepth" to make it clear of its purpose. – Tom 'Blue' Piddock May 09 '17 at 08:59
  • To clarify something: Are you worried about a tree structure in the object and only want ONE value to be converted to string or are you looking for ANY empty object leaf on this object tree being converted? – Tom 'Blue' Piddock May 09 '17 at 14:23
  • Any empty object, to try and account for all cases. But in my work environment scenario, we only know of this one instance of this occurring. – tchan May 10 '17 at 01:45
  • Okay, well as an empty object by definition can't have anything inside it to go deeper into, this makes it a lot easier to do: I've answered this below. Give it a shot. – Tom 'Blue' Piddock May 10 '17 at 10:52

2 Answers2

1
deeper=obj=>(Object.keys(obj[Object.keys(obj)[0]]).length&&deeper(obj[Object.keys(obj)[0]])&&true)||(obj[Object.keys(obj)[0]]="{}");
var obj={CONN_INFO: {CFGSwitch: {412: {}}}};
deeper(obj);
console.log(obj);

http://jsbin.com/nidahuhema/edit?console

Why do you check for the depth and then go into it? cant you just do it all in one?

The long form of the upper code:

function deeper(obj){
  if(Object.keys(Object.values(obj)[0]).length){ // if the child object has properties
    return deeper(Object.values(obj)[0]);
  }
  obj[Object.keys(obj)[0]]="{}";
}
Jonas Wilms
  • 132,000
  • 20
  • 149
  • 151
  • I check for depth because this only happens after the third level. If I applied the recursive function to all my data within the table, it just freezes my browser. Writing recursive functions makes my head spin, but this solution works for me though, so thank you :) – tchan May 09 '17 at 02:15
  • The problem with your function though, is if there's no empty object, for example if I change the empty object to a string, `var obj={CONN_INFO: {CFGSwitch: {412: "1"}}};` you will get a RangeError: maxium call stack size exceeded – tchan May 09 '17 at 03:16
1

Firstly lets combine some knowledge:

How do I test for an empty JavaScript object?

The above question has an awesome answer with many options in it, I'm going to edit the snippets to form a couple of functions:

function isObject (obj) {
    return obj.constructor === Object;
}

function isEmptyObject (obj) {    
    return Object.keys(obj).length === 0 && isObject(obj);
}

Ace. Now, assuming you have a very linear object structure, it's not a complex array and don't care about the depth (only that it is empty) lets make a function loop through the tree.

function convertEmptyObjects (obj, currentDepth) {
    currentDepth = currentDepth || 0;
    for (var key in obj) {
        var val = obj[key];
        if (isObject(val)) {
            if (isEmptyObject(val)) {
                obj[key] = "{}";
                console.log("Defeated boss ("+ key +") on level "+ currentDepth +"!");
            }else{
                convertDeepestEmptyObject (val, currentDepth + 1);                    
            }
        }
    }
    return obj;
}

Lets test this on an awful looking object:

var testObject = {
    CONN_INFO: {
        CFGSwitch: {
            412: {}, // Level 2
            413: {
                content: {}  // Level 3
            }
        },
        DummySwitch: {} // Level 1
    },
    TEST_CONN_INFO: {
        CFGSwitch: {
            414: {},  // Level 2
            415: {
                content: {
                    host: "google",
                    port: "8080",
                    protocol: {}  // Level 4
                }
            }
        }
    },
    STAGING_CONN_INFO: {} // Level 0
}

convertEmptyObjects(testObject);
JSON.stringify(testObject)

/* Output:
* Defeated boss (412) on level 2!
* Defeated boss (content) on level 3!
* Defeated boss (DummySwitch) on level 1!
* Defeated boss (414) on level 2!
* Defeated boss (protocol) on level 4!
* Defeated boss (STAGING_CONN_INFO) on level 0!
*/

// Result:
{
    "CONN_INFO": {
        "CFGSwitch": {
            "412": "{}", // Empty String {}
            "413": {
                "content": "{}" // Empty String {}
            }
        },
        "DummySwitch": "{}" // Empty String {}
    },
    "TEST_CONN_INFO": {
        "CFGSwitch": {
            "414": "{}", // Empty String {}
            "415": {
                "content": {
                    "host": "google",
                    "port": "8080",
                    "protocol": "{}" // Empty String {}
                }
            }
        }
    },
    "STAGING_CONN_INFO": "{}" // Empty String {}
}

There you have it.

Community
  • 1
  • 1
Tom 'Blue' Piddock
  • 2,131
  • 1
  • 21
  • 36