I have implemented a recursive function that converts an objects keys according to another lookup table/map. You are able to convert back and forth using the 3rd `swap_conversion_table_key_value` boolean argument. My use case is to convert object keys to single characters to slim down the amount of characters generated from `JSON.stringify`. Then be able to convert it back to full keys on another client. Along with the usual code review criteria(mainly clarity), I am wondering if I just reinvented the wheel or overthought the whole problem. The code does seem a bit long for the functionality and I am not keen how how it directly modifies the object(wish it would return a new object). This means that you have to clone the data before every use to keep all the references to the original data happy. # [Demo: jsFiddle](http://jsfiddle.net/MadLittleMods/g3g0g1L4/) ![](https://i.imgur.com/OGYfjgX.png) Usage: recursiveConvertKeys(resultant_data, conversion_table, false); // 3rd parameter defines whether we should swap the key-value in the table/map (good for converting back to the original data) recursiveConvertKeys(resultant_data, conversion_table, true); Code: function recursiveConvertKeys(data_object, conversion_table, swap_conversion_table_key_value, __is_recursive_iteration, __current_object_level, __current_conversion_table_level) { /* Usage: var data = {asdf: 1, qwer: 2}; var conversion_table = {asdf: 'a', qwer: 'q'}; // Clone the data so we don't overwrite it var resultant_data = $.extend(true, {}, data); // Now execute the key converting process recursiveConvertKeys(resultant_data, conversion_table, false); console.log("Reversed Data:", resultant_data); // If you want to reverse the process simply pass true for the `swap_conversion_table_key_value` argument recursiveConvertKeys(resultant_data, conversion_table, true); console.log("Back to normal Data:", resultant_data); */ // // Do not pass in parameters for the double underscore arguments. These are private and only used for self recursive calling // Start at the root of the objects when we invoke this method __current_object_level = __is_recursive_iteration ? __current_object_level : data_object; __current_conversion_table_level = __is_recursive_iteration ? __current_conversion_table_level : conversion_table; if(typeof __current_object_level == "object") { // Make the iterate object var iterate_object = Object.keys(__current_object_level); //console.log('iter', iterate_object); iterate_object.map(function(key, index, array) { // Check to make sure this is part of the object itself if (__current_object_level.hasOwnProperty(key)) { if(__current_conversion_table_level) { var new_key = null; if(!swap_conversion_table_key_value) { if(typeof __current_conversion_table_level[key] == "object") new_key = __current_conversion_table_level[key]['_short']; else new_key = __current_conversion_table_level[key]; } else { // We have to search through all of the current level to match the value to curernt object key since we swapped var table_level_keys = Object.keys(__current_conversion_table_level); for(var i = 0; i < table_level_keys.length; i++) { var curr_level_table_key = table_level_keys[i]; var key_to_compare = null; var curr_level_table_value = __current_conversion_table_level[curr_level_table_key]; if(typeof curr_level_table_value == "object") key_to_compare = curr_level_table_value['_short']; else key_to_compare = curr_level_table_value; // If it is a match, we found it :) if(key_to_compare == key) { // Now use the key from the conversion table instead of the value new_key = curr_level_table_key; // Break out of the for loop after we found it break; } } } // If there is actually a new key, replace it in our object if(new_key) { renameProperty(__current_object_level, key, new_key); } //console.log('key', key, new_key); // Only keep going if there actually was a new_key // Or there is a array to look through the items on var is_current_key_array_index = key%1 == 0; // If the current key is a positive integer, we assume it is an array key if(new_key || is_current_key_array_index) { // Use the new key if it was available // Because that is what the object property is changed to from above var value = __current_object_level[new_key ? new_key : key]; //console.log('current', value, __current_conversion_level); // If we are swapping then the `key` will not be found in the table as it is ass-backwards. var table_key = swap_conversion_table_key_value ? new_key : key; // If the current key is a array, maintain the `_array_item` conversion level we set the level prior // Otherwise continue down the tree var next_conversion_level = is_current_key_array_index ? __current_conversion_table_level : __current_conversion_table_level[table_key]; if(typeof __current_conversion_table_level[table_key] == "object") { // If the current value is an array set up the conversion level for the items if(Object.prototype.toString.call(value) === '[object Array]') { next_conversion_level = __current_conversion_table_level[table_key]['_array_item']; } else { next_conversion_level = __current_conversion_table_level[table_key]['_object']; } } //console.log('next', next_conversion_level); recursiveConvertKeys(data_object, conversion_table, swap_conversion_table_key_value, true, value, next_conversion_level); } } } }); } } --- The format for the conversion table is below. I am not set on this format so feel free to suggest something better for the table/map. var conversion_table = { "psdf": "p", "qwer": "q", "array": { "_short": "a" }, "candidates": { "_short": " ", "_array_item": { "ip": "i", "port": "p" } } } And some accompanying test data: var test_data = { "psdf": "pcodereview", "qwer": "qcodereview", "array": [ "1", "2", "3" ], "candidates": [ { "ip": "0.0.0.0", "port": 65000 }, { "ip": "127.0.0.1", "port": 65000 } ] }