Thursday, February 6, 2014

Converting a URL string into Json

I was making a website the other day and I wanted to somehow pass variables that can be read with javascript. So if the user browsed to
http://www.example.com?height=100px&width=50px, the variables height and width should be read from javascript. Note that this method of passing the variables in the URL is used most notably for CGI, aka server-side scripting(PHP anyone?).

JSON


So I was a bit puzzled while looking around at stackoverflow as many people do think that there is something magical about Json. Json is nothing more than a standard on how things are stored. The standard pretty much sums up to this:

  1. Variables are stored as varName = value

  2. Arrays are stored as arrayName = [value1, value2, value3 .. ]

  3. A value can be: a number, a string, true, false, none

  4. The whole thing is encapsulated in wavy braces



For my example, the Json structure(after parsing the URL string) should look like this:
[sourcecode language="javascript" light="true"]
{
"height": "100px"
"width" : "50px"
}
[/sourcecode]

In this case the values are strings. Keep in mind however that according to the standard, they could be anything between a number, a string, true, false and none.

My parser


So to get this structure from the URL, I needed some kind of parsing. All the solutions I found either used regular expressions, or they wanted a whole library to be imported, or just didn't support arrays. So I made up my own ugly solution.

The function url2json() uses pure JavaScript code which doesn't use regular expressions and accepts both arrays and variables:

[sourcecode language="javascript"]
function url2json(url) {
var obj={};

function arr_vals(arr){
if (arr.indexOf(',') > 1){
var vals = arr.slice(1, -1).split(',');
var arr = [];
for (var i = 0; i < vals.length; i++)
arr[i]=vals[i];
return arr;
}
else
return arr.slice(1, -1);
}

function eval_var(avar){
if (avar[1].indexOf('[') == 0)
obj[avar[0]] = arr_vals(avar[1]);
else
obj[avar[0]] = avar[1];
}

if (url.indexOf('?') > -1){
var params = url.split('?')[1];
if(params.indexOf('&') > 2){
var vars = params.split('&');
for (var i in vars)
eval_var(vars[i].split('='));
}
else
eval_var(params.split('='));
}

return obj;
}
[/sourcecode]

To keep things clean, all values are parsed into strings. As the input of the function is a string it just makes sense to give back strings so no extra processing takes place if it's not needed(checking if every value is of a certain type). It's up to the user to convert the strings into numbers or whatever they want, if they really have to.

Parsing variables


To use the function with the example above, I would just run
[sourcecode language="javascript" light="true"]
obj = url2json("http://www.example.com?height=100px&amp;width=50px
");
console.log(obj.height);
console.log(obj.width);
[/sourcecode]

Launching the console in the browser(CTRL+SHIFT+K), we get the results:
[sourcecode language="javascript" light="true"]
"100px"
"50px"
[/sourcecode]

Parsing arrays


Arrays are parsed like this
[sourcecode language="javascript" light="true"]
obj = url2json("www.x.com?numbers=[100,45,88,90]&mixed=[red,56,blue,20]");
console.log(obj);
[/sourcecode]

The object logged in the console looks like this:
[sourcecode language="javascript" light="true"]
{
"numbers" : ["100", "45", "88", "90"]
"mixed" : ["red", "56", "blue", "20"]
}
[/sourcecode]