index.js
function(obj) {
	if (_.isArray(obj)) {
		for (var i = 0; i < obj.length; i++) {
			obj[i] = walker(obj[i]);
		}
	} else if (_.isPlainObject(obj)) {
		var newObj = {};
		for (var k in obj) {
			if (!obj.hasOwnProperty(k)) continue;
			var include = true;
			if (options.renameFields[k]) {
				newObj[options.renameFields[k]] = obj[k];
				include = false;
			}

			for (var rf in options.removeFields) {
				if (_.isRegExp(options.removeFields[rf])) {
					if (options.removeFields[rf].test(k)) include = false;
				} else { // Assume its a function
					if (options.removeFields[rf].test(obj[k], k)) include = false;
				}
				if (!include) break;
			}

			if (include) newObj[k] = walker(obj[k]);
		}
		obj = newObj;
	} else if (_.isObject(obj)) {
		return obj.toString();
	}
	return obj;
}
function(obj) {
	if (_.isArray(obj)) {
		for (var i = 0; i < obj.length; i++) {
			obj[i] = walker(obj[i]);
		}
	} else if (_.isPlainObject(obj)) {
		var newObj = {};
		for (var k in obj) {
			if (!obj.hasOwnProperty(k)) continue;
			var include = true;
			if (options.renameFields[k]) {
				newObj[options.renameFields[k]] = obj[k];
				include = false;
			}

			for (var rf in options.removeFields) {
				if (_.isRegExp(options.removeFields[rf])) {
					if (options.removeFields[rf].test(k)) include = false;
				} else { // Assume its a function
					if (options.removeFields[rf].test(obj[k], k)) include = false;
				}
				if (!include) break;
			}

			if (include) newObj[k] = walker(obj[k]);
		}
		obj = newObj;
	} else if (_.isObject(obj)) {
		return obj.toString();
	}
	return obj;
}
Walker function to iterate though the collection / array / object tree
@param mixed obj The object to iterate over
@return Either the incomming object or the rewritten object without any bad fields