Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Efficiently rename/re-map javascript/json object keys within array of objects

Tags:

I have some structured JSON data like so. Let's assume this is interchangeable, via JSON.parse():

[     {         "title": "pineapple",         "uid": "ab982d34c98f"     },     {         "title": "carrots",         "uid": "6f12e6ba45ec"     } ] 

I need it to look like this, remapping title to name, and uid to id with the result:

[     {         "name": "pineapple",         "id": "ab982d34c98f"     },     {         "name": "carrots",         "id": "6f12e6ba45ec"     } ] 

The most obvious way of doing it is like this:

str = '[{"title": "pineapple","uid": "ab982d34c98f"},{"title": "carrots", "uid": "6f12e6ba45ec"}]';  var arr = JSON.parse(str); for (var i = 0; i<arr.length; i++) {     arr[i].name = arr[i].title;     arr[i].id = arr[i].uid;     delete arr[i].title;     delete arr[i].uid; } 

str = '[{"title": "pineapple","uid": "ab982d34c98f"},{"title": "carrots",    		"uid": "6f12e6ba45ec"}]';    var arr = JSON.parse(str);  for (var i = 0; i<arr.length; i++) {      arr[i].name = arr[i].title;      arr[i].id = arr[i].uid;      delete arr[i].title;      delete arr[i].uid;  }    $('body').append("<pre>"+JSON.stringify(arr, undefined, 4)+"</pre>");
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

...or using something more complex (albeit not more efficient) like this.

This is all fine and dandy, but what if there were 200,000 objects in the array? This is a lot of processing overhead.

Is there a more efficient way to remap a key name? Possibly without looping through the entire array of objects? If your method is more efficient, please provide proof/references.

like image 224
brandonscript Avatar asked Jan 15 '14 21:01

brandonscript


1 Answers

As I already mentioned in the comments, if you can make certain assumptions about the values of the objects, you could use a regular expression to replace the keys, for example:

str = str.replace(/"title":/g, '"name":'); 

It's not as "clean", but it might get the job done faster.


If you have to parse the JSON anyway, a more structured approach would be to pass a reviver function to JSON.parse and you might be able to avoid an additional pass over the array. This probably depends on how engine implement JSON.parse though (maybe they parse the whole string first and then make a second pass with the reviver function, in which case you wouldn't get any advantage).

var arr = JSON.parse(str, function(prop, value) {    switch(prop) {      case "title":         this.name = value;         return;      case "uid":         this.id = value;         return;      default:         return value;    } }); 

Benchmarks, using the Node.js script below to test 3 times:

1389822740739: Beginning regex rename test 1389822740761: Regex rename complete // 22ms, 22ms, 21ms 1389822740762: Beginning parse and remap in for loop test 1389822740831: For loop remap complete // 69ms, 68ms, 68ms 1389822740831: Beginning reviver function test 1389822740893: Reviver function complete // 62ms, 61ms, 60ms 

It appears as if the regex (in this case) is the most efficient, but be careful when trying to parse JSON with regular expressions.


Test script, loading 100,230 lines of the OP's sample JSON:

fs = require('fs'); fs.readFile('test.json', 'utf8', function (err, data) {     if (err) {         return console.log(err);     }     console.log(new Date().getTime() + ": Beginning regex rename test");     var str = data.replace(/"title":/g, '"name":');     str = str.replace(/"uid":/g, '"id":');     JSON.parse(str);     console.log(new Date().getTime() + ": Regex rename complete");     console.log(new Date().getTime() + ": Beginning parse and remap in for loop test");     var arr = JSON.parse(data);     for (var i = 0; i < arr.length; i++) {         arr[i].name = arr[i].title;         arr[i].id = arr[i].uid;         delete arr[i].title;         delete arr[i].uid;     }     console.log(new Date().getTime() + ": For loop remap complete");     console.log(new Date().getTime() + ": Beginning reviver function test");     var arr = JSON.parse(data, function (prop, value) {         switch (prop) {             case "title":                 this.name = value;                 return;             case "uid":                 this.id = value;                 return;             default:                 return value;         }     });     console.log(new Date().getTime() + ": Reviver function complete"); }); 
like image 100
Felix Kling Avatar answered Sep 24 '22 13:09

Felix Kling