Generate JSON from VBScript (ASP) datatypes
When working with JSON it's nice to have a generator for your language which transforms all the datatypes from your chosen programming language into the JSON grammar so that you can use them within javascript. For a lot of popular languages it's done already (i suppose) but I haven't found one for classic ASP .. so here it comes. The following example quickly demonstrates what the goal is:
-
set RS = getRecordset("SELECT * FROM table")
-
response.write((new JSON).toJSON("rows", RS))
A simple usage of JSON normally is that you create a page which outputs data as JSON as the only response. This page is called later from another page and the returned data is used within a javascript function (known as callback). So the snippet above gets some data from the database and stores it in an adodb.recordset which is passed then to the JSON generator and the result is printed on the page. The consuming page would like to access the data now as it originally was within the recordset. like this:
-
function callback(rows) {
-
for (i = 0; i <rows.length; i++) {
-
alert(rows[i].columName);
-
}
-
}
read on to get the details...
If you are already impressed by the short example then you will save a lot of time from now on when working with JSON. I have written a class which handles the whole conversation of classic ASP datatypes to JSON grammar. In particular an ASP boolean is recognized as a boolean within javascript, an integer as a number, an array as an array, a recordset as collection, etc. I will come back to the first example later but first another example:
-
<script>
-
alert(<%= (new JSON).toJSON("foo", array(true, 1, ""), false) %>.foo[0]);
-
</script>
This short snippet displays an alert with true. As you can see we passed an ASP variable which has been recognized later by javascript. In this very example we even pass an array with 3 different datatypes (boolean, int and string). Those are all accessible within javascript.
Even nesting is fully supported. So array within arrays, dictionaries within arrays and vice versa. Mixing is allowed in every way you imagine. This example demonstrates what i am talking about:
-
<%
-
set d = server.createObject("scripting.dictionary")
-
d.add "en", "sausage"
-
d.add "de", array("egal", "wurst")
-
%>
-
<script>
-
alert(<%= (new JSON).toJSON("foo", array(d), false) %>.foo[0].de[1]);
-
</script>
We've created a dictionary (which consists of two value pairs - one holds just a string (sausage) and the other an array (egal, wurst)) and we've added this into another array which is the value of "foo". After toJSON has generated the JSON string we can access the whole structure and the alertbox says "wurst".
Now back to the example of the introduction. We can even pass whole recordsets to the generator which will generate a datastructure as followed:
JSON representation for ADODB.recordset
a recordset with two columns ID and LASTNAME will be converted into a javascript array where each field represents a row in the field and the row provides properties which are named the same as the columns within the recordset. That means that iterating through data within javascript is not a mission anymore ... look at this example:
-
<script>
-
alert(<%= (new JSON).toJSON("data", getRecordset("SELECT id, lastname FROM table"), false) %>.data[0].lastname);
-
</script>
We transfered the whole adodb.recordset from ASP to javascript using JSON. How cool is that!?
Custom classes
If you create your own classes within VBScript then you might like the automatic conversion of your objects into a JSON representation. As VBScript does not support introspection (reflection) it is necessary to built an own work around. If you want the JSON class to recognize your custom objects it is necessary to implement a reflect() method within the custom type. reflect() must return a dictionary with all properties where each key is the property name and the value is its value. Values can be all kind of types (because its resolved recursively anyway). The following example shows a "Person" class which implements reflect() and therefore can be used within the JSON generator:
-
class Person
-
public firstname ''[string] firstname
-
public lastname ''[string] lastname
-
public favNumbers ''[array] persons favorite numbers
-
-
public function reflect()
-
set reflect = server.createObject("scripting.dictionary")
-
with reflect
-
.add "firstname", firstname
-
.add "lastname", lastname
-
.add "favNumbers", favNumbers
-
end with
-
end function
-
end class
The following example access the properties of the VBScript Person class within JavaScript (as it would be a JavaScript object).
-
<%
-
set p = new Person
-
p.firstname = "John"
-
p.lastname = "Doe"
-
p.favNumbers = array(2, 7, 234)
-
%>
-
<script>
-
alert(<%= (new JSON).toJSON("p", p, false) %>.p.favNumbers[0]);
-
</script>
Update 10.07.2008: as the toJSON()
method has been defined as default method it can be used much quicker by leaving the methodname out:
-
<script>
-
alert(<%= (new JSON)("root", "some value", false) %>.root);
-
</script>
Those examples are really straight forward and should just demonstrate how to use the generator. Normally you don't really deal with that as a client, you'd rather have some nice classes which do all this stuff for you. In another article I will demonstrate how to combine ASP, JSON and AJAX in a nice and effective way...
The download of the class is at the bottom. Here is a list of the features..
- Transforms various datatypes from ASP to Javascript using JSON
- Escapes all characters which needs to be escaped according to JSON's RFC
- Recursively inspects the values so nesting of values is supported
- Results can be returned or (for better performance) written directly to the response
Have fun with it. There are other article related to this topic which might be interested for you:
- JSON character escaping function in classic ASP
- ajaxed Library - calling server side ASP code directly from client side.
Download latest JSON ASP utility class:
JSON 1.5.1 (JSON documentation)
License:
Use it for whatever you want but be sure to leave the credits to the creator(s) within the code. If you don't change it you can get always the latest update here ;)
Change Log:
v1.5.1 (15.07.2008)
- bugfix: didnt work properly with empty dictionaries. fixed!
v1.5 (10.07.2008)
- bugfix: utf-8 fully supported now (e.g. chinese didnt work)
- bugfix: empty dictionaries werent represented. now represented as 'null'
- toJSON() is defined as default method
- paged recordsets supported
- asp request object, IStringList and IRequestDictionary supported
- updated documentation
- detailed information (examples, ...) about the changes
v1.4.1 (19.12.2007)
- minor bugfix immediately after the 1.4 release
v1.4 (18.12.2007)
- there used to be an error when returning custom objects which were processed recursively. it resulted in outputing only '}'. this has been fixed.
- vartype 19 was not recognized as integer, but is now (comes from mysql)
- vartype 7 was not recognized as float, but is now
v1.3 (21.08.2007)
- Option Explicit can be used now
- Multidimensional arrays are supported (unlimited dimensions)
v1.2 (19.07.2007)
- Nested dictionaries were are not generated with toResponse = false. Fixed
- Currency and Byte datatype were not generated correctly. Fixed
v1.1 (17.05.2007)
- Bug with Floats has been fixed