Search code examples
javascriptrecursiondata-structuresfunctional-programmingmootools

Deep changing values in a JavaScript object


I have an object which contains an unknown number of other objects. Each (sub-)object may contain boolean values as strings and I want to change them to real boolean values. Here's an example object:

var myObj = {
  my1stLevelKey1: "true",
  my1stLevelKey2: "a normal string",
  my1stLevelKey3: {
    my2ndLevelKey1: {
      my3rdLevelKey1: {
        my4thLevelKey1: "true",
        my4thLevelKey2: "false"
      }
    },
    my2ndLevelKey2: {
      my3rdLevelKey2: "FALSE"
    }
  }
}

What I want in the end is this:

var myObj = {
  my1stLevelKey1: true,
  my1stLevelKey2: "a normal string",
  my1stLevelKey3: {
    my2ndLevelKey1: {
      my3rdLevelKey1: {
        my4thLevelKey1: true,
        my4thLevelKey2: false
      }
    },
    my2ndLevelKey2: {
      my3rdLevelKey2: false
    }
  }
}

Important is that the number sub-objects/levels is unknown. How can I do this effectively by either using classic JavaScript or Mootools?


Solution

  • Recursion is your friend

    (function (obj) { // IIFE so you don't pollute your namespace
        // define things you can share to save memory
        var map = Object.create(null);
        map['true'] = true;
        map['false'] = false;
        // the recursive iterator
        function walker(obj) {
            var k,
                has = Object.prototype.hasOwnProperty.bind(obj);
            for (k in obj) if (has(k)) {
                switch (typeof obj[k]) {
                    case 'object':
                        walker(obj[k]); break;
                    case 'string':
                        if (obj[k].toLowerCase() in map) obj[k] = map[obj[k].toLowerCase()]
                }
            }
        }
        // set it running
        walker(obj);
    }(myObj));
    

    The obj[k].toLowerCase() is to make it case-insensitive