Is the usage of eval() justified here? - javascript

The JavaScript object data has an attribute 'amplitudes' which is a string concatenated bunch of bitmask arrays coming from the server.
var data = {
"amplitudes":
"[1,1,1,4,1,1],[1,1,1,1,1,1],[1,1,4,1,9,1],[1,1,9,1,16,1],[1,32,1,1,1,9],[4,4,4,1,1,1]"
}
.
This needs be broken down into six independant arrays. I am using a combination of split() and eval() to accomplish it in the following way:
var amplitudes = [];
amplitudes = data.amplitudes.split("],[");
for(var i=0;i<amplitudes.length;i+=1){
(i+1)%2>0 ? amplitudes[i] = amplitudes[i] + "]" : amplitudes[i] = "[" + amplitudes[i];
amplitudes[i] = eval(amplitudes[i]);
}
Questions
1) Is there a more elegant and efficient way to do this?? I am not too happy with the usage of eval(), but had a feeling split is more efficient than a regex? I haven't run a benchmark yet.
2) I am also open to manipulating the format in which the field 'amplitudes' is stored in database so that my overall design gets simpler.
Suggestions welcome

As you probably process your data with a server-side language simply make it generate a JavaScript array. If you have an array in your server-side code, use a JSON encoder to build the JavaScript object/array.
var data = {
"amplitudes": [[1,1,1,4,1,1], [1,1,1,1,1,1], [1,1,4,1,9,1], [1,1,9,1,16,1], [1,32,1,1,1,9], [4,4,4,1,1,1]]
}
If you cannot change what you get from the server, you can do it using eval but in a much simpler way:
var str = "[1,1,1,4,1,1],[1,1,1,1,1,1],[1,1,4,1,9,1],[1,1,9,1,16,1],[1,32,1,1,1,9],[4,4,4,1,1,1]";
var arr = eval('[' + str + ']');

If you can change the server, just have the "amplitudes" property be an array of arrays, and don't write it out with quotes:
var data = {
amplitudes: [ [1, 1, 1, 4, 1, 1 ], [ 1, 1, 1, 1, 1, 1 ], ... ]
};
Now your client need do no decoding at all.

The eval() function is generally used to decode JSON data that is considered 'safe', as using eval on user-defined data can result in XSS attacks. Anyway, you can make your code more elegant by using regular expressions to match the arrays, then use eval to decode the array components:
var matches = data.amplitudes.match(/\[.*?\]/g);
var amplitudes = [];
if (matches != null && matches.length > 0) {
for (var i = 0; i < matches.length; i++) {
amplitudes[i] = eval(matches[i]);
}
}

Well you could try using JSON to pass a javascript object directly from the server, compared to just returning a string. Almost every server side language supports JSON encoding/decoding in some form.
http://www.json.org/

Related

Replacing custom characters during string.split()

I have a fairly large javascript/html application that updates frequently and receives a lot of data. It's running very quickly and smoothly but I need to now introduce a function that will have to process any incoming data for special chars, and I fear it will be a lot of extra processing time (and jsperf is kinda dead at the moment).
I will make a request to get a .json file via AJAX and then simply use the data as is. But now I will need to look out for strings with #2C (hex comma) because all of the incoming data is comma-separated values.
in File.json
{
names: "Bob, Billy",
likes : "meat,potatoes
}
Now I need
{
names: "Bob, Billy",
likes : "meat#2Cbeear#2Cwine,potatoes
}
where #2C (hex for comma) is a comma within the string.
I have this code which works fine
var str = "a,b,c#2Cd";
var arr = str.split(',');
function escapeCommas(arr) {
for (var i = 0; i < arr.length; i++) {
if (arr[i].indexOf("#2C") !== -1) {
var s = arr[i].replace("#2C", ',');
arr[i] = s;
}
}
return arr;
}
console.log(escapeCommas(arr));
http://jsfiddle.net/5hogf5me/1/
I have a lot of functions that process the JSON data often as
var name = str.split(',')[i];
I am wondering how I could extend or re-write .split to automatically replace #2C with a comma.
Thanks for any advice.
Edit: I think this is better:
var j = {
names: "Bob, Billy",
likes : "meat#2Cpotatoes"
};
var result = j.likes.replace(/#2C/g, ',');
// j.likes.replace(/#2C/ig, ','); - if you want case insensitive
// and simply reverse parameters if you want
console.log(result);
This was my initial approach:
var j = {
names: "Bob, Billy",
likes : "meat,potatoes"
}
var result = j.likes.split(",").join("#2C")
console.log(result);
// meat#2Cpotatoes
Or if you have it the reverse:
var j = {
names: "Bob, Billy",
likes : "meat#2Cpotatoes"
}
var result = j.likes.split("#2C").join(",")
console.log(result);
// meat,potatoes
[Updated to reflect feedback] - try at http://jsfiddle.net
var str = 'a,b,c#2Cd,e#2Cf#2Cg';
alert(str.split(',').join('|')); // Original
String.prototype.native_split = String.prototype.split;
String.prototype.split = function (separator, limit) {
if ((separator===',')&&(!limit)) return this.replace(/,/g,'\0').replace(/#2C/gi,',').native_split('\0');
return this.native_split(separator, limit);
}
alert(str.split(',').join('|')); // Enhanced to un-escape "#2C" and "#2c"
String.prototype.split = String.prototype.native_split;
alert(str.split(',').join('|')); // Original restored
Couple minor tangential notes about your function "escapeCommas": this function is really doing a logical "un-escape" and so the function name might be reconsidered. Also, unless it is your intention to only replace the first occurence of "#2C" in each item then you should use the "g" (global) flag, otherwise an item "c#2Cd#2Cde" would come out "c,d#2Ce".

Transform JSON Object into numerical String and vice versa

(Apologies if a similar question has been asked, I could not find it)
Basically I have a JSON object with around 10 properties (fixed amount) that contains personal settings for an app without a user system and I would like users to be able to obtain a code that converts to that object with the proper values for each property. That way, they would be able to access the app with their settings using a permalink.
Question is: Is there a method or a specific indicated technique to transform JSON serialized objects (i.e. JSON string) into numbers, or an hexadecimal code? I've seen several websites do a similar thing from a user point of view.
My approach since I have a finite set of properties and possible values would be to hardcode the string (e.g. if property 1 has value x, first char in string is 1, if it has value y, then it's 2, etc...) but I'm wondering if there is anything best suited for that kind of thing.
Lets do this.
setup is object I used for testing
var setup = { "abc" : "asdasd",
"special" : "my wife hates me",
"Kids" : 7564
};
function to generate link:
function generateLinkWithSpecialSetup(setup) {
var str = JSON.stringify(setup);
var hash = "";
for(var i =0; i<str.length;i++) {
hash += str.charCodeAt(i).toString(16);
}
return "example.com/special-setup/#" + hash;
}
functions to find setup from hash:
function findSetupFromHash() {
var hash = window.location.hash.substring(1);
var str = hex2a(hash);
return JSON.parse(str);
}
function hex2a(hexx) {
var hex = hexx.toString(); //force conversion
var str = '';
for (var i = 0; i < hex.length; i += 2)
str += String.fromCharCode(parseInt(hex.substr(i, 2), 16));
return str;
}

javascript serialization - a short library

I have to save in a cookie a small amount of data.
Would be wonderful if javascript (natively) provide a way to serialize/deserialize an array (or an object).
To be honest, I have tried to write my own piece of code, it is based on the idea that we could serialize an array recursively converting it in a key/value querystring and viceversa.
Well, this is the code:
var lib = {
serialize : function(_a) {
var s = '', enc = encodeURIComponent;
for (var k in _a) {
if (s) s += '&';
s += enc(k) + '=' + ((typeof _a[k] == 'object') ? '?'+enc(lib.serialize(_a[k])) : enc(_a[k]));
}
return s;
},
deserialize : function(_s) {
var a = [], dec = decodeURIComponent;
var list = _s.split('&');
for (var c in list) {
var kv = list[c].split('=');
var v = kv[1].split('?');
kv[1] = (v.length > 1) ? lib.deserialize(dec(v[1])) : dec(kv[1]);
a[dec(kv[0])] = kv[1];
}
return a;
}
};
http://jsfiddle.net/P7wT8/
Although it seems to works quite fine, could someone suggest me something of better and shorter?
A piece of code or a library, something of little and easy to implement Javascript array serialize/deserialize ?
I think your best approach is to use JSON.
JSON.stringify and JSON.parse can encode and decode the values.
JSON is a standard format nowadays, so it is clearer to other developers what's happening.
The only limitation is that IE 7 and below do not support JSON functions natively and require a library.

jsons with different fields every time

I've been searching for an answer but couldn't find it.
I have a json like this:
followersperdate{
'date2012-08-29': 16823,
'date2012-07-09': 15571,
'date2012-07-07': 15528,
'date2012-06-25': 15237,
'date2012-04-19': 13283,
'date2012-03-16': 12999,
etc.
}
and I want to get the values; but everytime I make the request, I recieve other dates. I don't know how to get the values.
I've tried with jsonpath but didn't work.
This is pretty trivial using DefiantJS (http://defiantjs.com). This lib extends the global object JSON with the method "search". Using this method, you can search a JSON structure, regardless of depth for values. It returns an array with the matches (empty array if no matches were found).
To get acquainted with XPath, check out this valuable resource;
http://www.defiantjs.com/#xpath_evaluator
Check out this fiddle;
http://jsfiddle.net/hbi99/DKuAQ/
var data = {
"date2012-08-29": 16823,
"date2012-07-09": 15571,
"date2012-07-07": 15528,
"date2012-06-25": 15237,
"date2012-04-19": 13283,
"date2012-03-16": 12999
},
res = JSON.search( data, '//*' ),
str = '';
for (var i=0; i<res.length; i++) {
str += res[i] +'<br/>';
}
document.getElementById('output').innerHTML = str;

how to load two dimensional array in javascript

I have a string containing many lines of the following format:
<word1><101>
<word2><102>
<word3><103>
I know how to load each line into an array cell using this:
var arrayOfStuff = stringOfStuff.split("\n");
But the above makes one array cell per line, I need a two-dimensional array.
Is there a way to do that using similar logic to the above without having to re-read and re-process the array. I know how to do it in two phases, but would rather do it all in one step.
Thanks in advance,
Cliff
It sounds like you're hoping for something like Python's list comprehension (e.g. [line.split(" ") for line in lines.split("\n")]), but Javascript has no such feature. The very simplest way to get the same result in Javascript is to use a loop:
var lines = lines.split("\n");
for (var i = 0; i < lines.length; i++) {
lines[i] = lines[i].split(" ");
// or alternatively, something more complex using regexes:
var match = /<([^>]+)><([^>]+)>/.exec(lines[i]);
lines[i] = [match[1], match[2]];
}
Not really. There are no native javascript functions that return a two-dimensional array.
If you wanted to parse a CSV for example, you can do
var parsedStuff = [];
stringOfStuff.replace(/\r\n/g, '\n') // Normalize newlines
// Parse lines and dump them in parsedStuff.
.replace(/.*/g, function (_) { parsedStuff.push(_ ? _.split(/,/g)) : []; })
Running
stringOfStuff = 'foo,bar\n\nbaz,boo,boo'
var parsedStuff = [];
stringOfStuff.replace(/\r\n/g, '\n')
.replace(/.*/g, function (_) { parsedStuff.push(_ ? _.split(/,/g)) : []; })
JSON.stringify(parsedStuff);
outputs
[["foo","bar"],[],["baz","boo","boo"]]
You can adjust the /,/ to suite whatever record separator you use.

Categories