最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

recursion - Deep changing values in a JavaScript object - Stack Overflow

programmeradmin2浏览0评论

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?

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?

Share Improve this question edited May 8, 2015 at 18:48 Peter Seliger 13.4k3 gold badges30 silver badges44 bronze badges asked May 8, 2015 at 16:41 TimoTimo 1831 gold badge2 silver badges8 bronze badges 1
  • you need a recursive iterator. look into json2.js to see how it traverses objects. you can also actually use a JSON revivor function. – dandavis Commented May 8, 2015 at 16:43
Add a comment  | 

4 Answers 4

Reset to default 20

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

Walk each level of the object and replace boolean string values with the appropriate booleans. If you find an object, recurse in and replace again.

You can use Object.keys to grab all the members of each object, without worrying about getting inherited properties that you shouldn't.

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

function booleanizeObject(obj) {
  var keys = Object.keys(obj);
  keys.forEach(function(key) {
    var value = obj[key];
    if (typeof value === 'string') {
      var lvalue = value.toLowerCase();
      if (lvalue === 'true') {
        obj[key] = true;
      } else if (lvalue === 'false') {
        obj[key] = false;
      }
    } else if (typeof value === 'object') {
      booleanizeObject(obj[key]);
    }
  });
}

booleanizeObject(myObj);

document.getElementById('results').textContent = JSON.stringify(myObj);
<pre id="results"></pre>

JavaScript data structures elegantly can be sanitized by recursive functional reduce approaches.

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


myObj = Object.keys(myObj).reduce(function sanitizeBooleanStructureRecursively (collector, key) {
  var
    source  = collector.source,
    target  = collector.target,

    value   = source[key],

    str
  ;
  if (value && (typeof value == "object")) {

    value = Object.keys(value).reduce(sanitizeBooleanStructureRecursively, {

      source: value,
      target: {}

    }).target;

  } else if (typeof value == "string") {

    str   = value.toLowerCase();
    value = ((str == "true") && true) || ((str == "false") ? false : value)
  }
  target[key] = value;

  return collector;

}, {

  source: myObj,
  target: {}

}).target;


console.log(myObj);

Plain javascript recursion example:

function mapDeep( obj ) {
    for ( var prop in obj ) {
        if ( obj[prop] === Object(obj[prop]) ) mapDeep( obj[prop] );
        else if ( obj[prop].toLowerCase() === 'false' ) obj[prop] = false;
        else if ( obj[prop].toLowerCase() === 'true' ) obj[prop] = true;
    }                   
};

And MooTools example, by extending the Object type with custom mapDeep() function:

Object.extend( 'mapDeep', function( obj, custom ) {
    return Object.map( obj, function( value, key ) {
        if ( value === Object( value ) )
            return Object.mapDeep( value, custom );
        else
            return custom( value, key );                    
    });
});


myObj = Object.mapDeep( myObj, function( value, key ) {
    var bool = { 'true': true, 'false': false };        
    return value.toLowerCase() in bool ? bool[ value.toLowerCase() ] : value;           
}) 
发布评论

评论列表(0)

  1. 暂无评论