简体   繁体   中英

How can I use Underscore.js to transform/obfuscate each value in an object

I'm trying to use Underscore.js to step through an object and transform/obfuscate each value, so that:

{
  "weather": "Cloudy",
  "degrees": 90
}

becomes:

{
  "weather": "Claido",
  "degrees": 21
}

The completely incomprehensible reason- I'm trying to obfuscate JSON objects without ruining their structure. So if it's string, I replace any vowel with another random vowel. If it's a digit, I just pick another random digit, booleans are set randomly, and so on. I can build each element type manipulation, I'm just now sure how to recursively do it.

I can do something like this:

var t = { "weather":"Cloudy", "degrees": 12, "snowing": false };
var newObj = {};
var g = _.each(t, function(value, key, list) {
  if (_.isString(value)){
     newObj[key] = value.replace(/[aeiou]/gi, '');
  }
  if (_.isNumber(value)){
     var n = Math.floor((Math.random()*10)+1);
     newObj[key] = n + value;
  }
  if (_.isBoolean(value)){
    newObj[key] = Math.random() >= 0.5;
  }
});
console.log(newObj);

And all is well. The problem is with arrays and nested objects like so:

{
 "weather": "Cloudy",
 "outsideWeather": {
     "forecast": "Stormy",
     "outside": 48
 },
 "degrees": 12,
 "snowing": false
}

My simple Switch cases break down at that point. Any ideas how to recursively step through each value, transform it, then build the object back to it's original structure?

Many thanks

function recurse(mem, val, key) {
  if (_.isObject(val)) {
    mem[key] = _.reduce(val, recurse, {});
  } else {
    mem[key] = obfuscate(val);
  }
  return mem;
}

function obfuscate(value) {
  return "bananas!"; // your obfuscate logic
}

var yourObject = {
  foo: "bar",
  baz: { bizz: "buzz", ok: true }
}

var o = _.reduce(yourObject, recurse, {});
console.log(o);

http://jsfiddle.net/uEwJY/

I've added the scramble function to underscore with mixin : http://jsfiddle.net/ejWCD/2/

var target = {
 "weather": "Cloudy",
 "outsideWeather": {
     "forecast": "Stormy",
     "outside": 48
 },
 "degrees": 12,
 "snowing": false
};

_.mixin({
    scramble: function(obj) {
        var newobj = {};
        _(obj).each(function(el, key) {
            switch( typeof el ) {
                case 'object':
                    newobj[key] = _(el).scramble();
                    break;
                case 'boolean':
                    newobj[key] = !el;
                    break;
                case 'string':
                    newobj[key] = el.replace(/[aeiou]/gi, 'aeiou'.charAt(_.random(4)));
                    break;
                case 'number':
                    newobj[key] = _.random(el*10);
                    break;
            }
        });
        return newobj;
    }
});

console.log( _(target).scramble() );

I'd do it like this:

var obfuscate = function(object) {
    if(_.isNumber(object)) {
        return object + 1;
    } else if(_.isString(object)) {
        return object.replace(/[aeiou]/gi, '');
    } else if(_.isBoolean(object)) {
        return Math.random() >= 5;
    } else if(_.isArray(object)) {
        return _.map(object, obfuscate);
    } else if(_.isObject(object)) {
        return _.object(_.map(object, function(value, key) {
            return [key, obfuscate(value)];
        }));
    }
}

Note: I'm not obfuscating the key . You can easily change a line of code if you want to do that. Also, if the object is an Array, I'm obfuscating every element.

Test:

var input = {
 "weather": "Cloudy",
 "outsideWeather": {
     "forecast": "Stormy",
     "outside": 48
 },
 "degrees": 12,
 "snowing": false
};

console.log(obfuscate(input));

http://jsfiddle.net/Dogbert/K2EML/

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM