Generate JSON from VBScript (ASP) datatypes

published on April 26, 2007 by Michal
category: AJAX, JSON, Javascript, ajaxed, classic ASP (VBScript)

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:

ASP:
  1. set RS = getRecordset("SELECT * FROM table")
  2. 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:

JAVASCRIPT:
  1. function callback(rows) {
  2.    for (i = 0; i <rows.length; i++) {
  3.       alert(rows[i].columName);
  4.    }
  5. }

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:

ASP:
  1. <script>
  2.    alert(<%= (new JSON).toJSON("foo", array(true, 1, ""), false) %>.foo[0]);
  3. </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:

ASP:
  1. <%
  2. set d = server.createObject("scripting.dictionary")
  3. d.add "en", "sausage"
  4. d.add "de", array("egal", "wurst")
  5. %>
  6. <script>
  7.    alert(<%= (new JSON).toJSON("foo", array(d), false) %>.foo[0].de[1]);
  8. </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:

ASP:
  1. <script>
  2.    alert(<%= (new JSON).toJSON("data", getRecordset("SELECT id, lastname FROM table"), false) %>.data[0].lastname);
  3. </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:

ASP:
  1. class Person
  2.     public firstname    ''[string] firstname
  3.     public lastname ''[string] lastname
  4.     public favNumbers   ''[array] persons favorite numbers
  5.    
  6.     public function reflect()
  7.         set reflect = server.createObject("scripting.dictionary")
  8.         with reflect
  9.             .add "firstname", firstname
  10.             .add "lastname", lastname
  11.             .add "favNumbers", favNumbers
  12.         end with
  13.     end function
  14. end class

The following example access the properties of the VBScript Person class within JavaScript (as it would be a JavaScript object).

ASP:
  1. <%
  2. set p = new Person
  3. p.firstname = "John"
  4. p.lastname = "Doe"
  5. p.favNumbers = array(2, 7, 234)
  6. %>
  7. <script>
  8.    alert(<%= (new JSON).toJSON("p", p, false) %>.p.favNumbers[0]);
  9. </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:

ASP:
  1. <script>
  2.    alert(<%= (new JSON)("root", "some value", false) %>.root);
  3. </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:

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
Google Groups
asp-ajaxed
JSON is part of ajaxed. So you can check the ajaxed discussion group for more discussion about it.
1 Star2 Stars3 Stars4 Stars5 Stars (62 votes, average: 4.45 out of 5)
Loading ... Loading ...

147 Responses to “Generate JSON from VBScript (ASP) datatypes”

  1. Bob says...

    ASP is not a language that has datatypes. I think you are talking about vbscript, but you need to remember that not even vbscript has datatypes per se. It has subtypes, but all variables are variants - yes, it is a fine distinction. Also, ASP can use jscript as well as vbscript in server-side code. Will your converter handle a jscript array as well as a vbscript array?

     
  2. michal says...

    hi bob, i am aware about the types (not types) in vbscript but i think you know what i mean ;) for jscript i dont think that it will be implemented ... at least not soon...

     
  3. Tom Stewart says...

    The License.txt is missing in the root JSON directory. Under what license did you release this great solution? May the JSON ASP file be used for commerical development?

     
  4. Michal says...

    hi tom i've just added a license note. you can use it for commercial development and your feedback is welcomed if you have any suggestions for improvements.

     
  5. JC says...

    Great work, I only wish I had access to this resource last year :)

    Keep up the good work!

     
  6. Trent says...

    Do you have a ASP Jscript version of this?

     
  7. DaveC426913 says...

    I'm not entirely sure how to incorporate this class into my ASP.NET app to turn a datatable into a JSON string (as well as the other way around).

    But I think it's a fair bit more complicated than this is it not?

    Dim dt As DataTable = readRecords()
    response.write(json.toJSON("records", dt, False))

    would simply give me

    {records:
    [
    {
    col1:val1_1,
    col2:val1_2
    },
    {
    col1:val2_1,
    col2:val2_2
    },
    ]
    }

     
  8. Michal says...

    @trent: no sorry unfortunately not cause i am using just vbscript for my ASP apps. maybe someone could come up with a clone ;)

     
  9. Michal says...

    hi dave, i wonder how you managed to run this within ASP.net because it is supposed to work with classic ASP only. If you are looking for generator for ASP.net check json.org there should be some links...

     
  10. DaveC426913 says...

    True. I didn't actually get it working. I found a C#.NET class from NewtonSoft.

     
  11. Michal says...

    i just googled it and here is the URL for all who are interested in an ASP.NET: http://www.newtonsoft.com/products/json/ in .net its even possible to serialize whole custom types which is not possible in classic ASP unfortunately. no iteration possibility through properties of classes :(

     
  12. Huy Dung says...

    I want to give you some special thanks for your great work, but I still have a problem: does a function which automatic generates variables/objects/arrays .... from a json string (send to server by ajax call) exist? There're many good-working functions like that in other languages, but in asp (with vbscript), I've found none :(

     
  13. Michal says...

    You mean a JSON parser dont you? so also the other way round.
    JSON => ASP

     
  14. Michal says...

    I've upped an updated version which fixes the "floats" bug. When using float it generated an integer and dropped the comma. this is fixed now.

     
  15. Cliff says...

    Hey Bob,
    I think you're maybe over-thinking & dealing with semantics here. Clearly VBScript is the dominant language for Classic ASP. As for data types, yes there may be a fine distinction, but the truth is that the distinction doesn't really matter when the end goal is to correctly translate the value into another format. The point is that ASP(VBS) gives you a hint as to what kind of data you're working with and that can be used to correctly translate the value into a JSON object.

    I would imagine anyone willing to go through the headaches of using JScript and VBScript in the same file would be able to modify the class to allow for JScript arrays. Inline JScript is parsed & run before any of the VBS on a page, so other than returning an array from a JScript function I wouldn't personally see much benefit in it. The mingling of VBS & JScript in a single file is definitely a huge weak spot in classic ASP that will never be fixed.

     
  16. Cliff says...

    Michael, if you're interested. I've found a few quirks & added a few things to the class. I can clean up the work & send it to you.

    The main quirk I've found is that nested Dictionaries trash the result. So lets say you create a dictionary of peoples names and every entry contains a dictionary of phone number, address, email, etc... Your JSON class just outputs:

    }}

    As for additions. I often use an ASP class I created that does a very similar thing to yours, only it does it with XML. My class also examines the data types and translates values as needed for items like arrays & dictionaries, and will nest to a (theoretically) unlimited depth. Like your class, one limitation is the ability to handle custom class definitions.

    While VBScript itself offers no inherent introspection for custom classes, the simple fox is to allow the developer of the class to implement JSON support which your class can then use. With minor changes I gave your class the ability to examine a custom class to see if it supports a 'toDictionary' property. If it does, then it will use the value returned from that method, rather than the object itself, and treat it as a dictionary.

    On the class developers side, they only need to implement a toDictionary method, which will grab any relevant values inside of the instance of their class and return a dictionary of name/value pairs. The items in that dictionary should be able to be of any type, including other objects, though the quirky nested dictionary bug I experienced would probably break that. Any class that does not support the method is treated as it is in your original class.

    Anyway, I'm happy to send you the changes if you want them. I'm assuming you have my email from this post.

     
  17. Vince says...

    I have have a need to retrieve values from a database using an ajax call. I have a form that I am collecting information on, I need to retrieve a database based on the values collected in the form (Pass some parameters to the database call), Once retrieved I need to perform calculations based on the retrieved data and submit the form for storage.
    I guess I can use the jason example to call the database values, but I want to retrieve the database without submitting the form. Will anything here you discussed to that?

     
  18. Michal says...

    hi cliff thanks a lot for your very helpful comments and its cool to see that ppl r using this stuff - especially still classic ASP ;) i am really interested in your cleaned up version and droppped you an mail about it. the introspection aproach sounds very interesting and i'll take a look into it when i have more time ... cheers

     
  19. Michal says...

    @vince: if you want to solve this with Ajax it should be a good way to use JSON for that and in this case that utitlity class. i am not sure how fit you are with asp but the following steps should help you:

    - create one page which generates the DB call and uses the JSON class to generate JSON output
    - create another page which holds the form and calls the JSON page with an XHR (e.g. Prototype) to retrieve the values.

    if you need help just let us know here ...

     
  20. moondy2 says...

    great helful. thank you~ ;)
    but , i met some problem using toJSON function

    foo.add "aaa","bb/cc"

    using "/" in Dictionary . runtime error occured =(
    how can i fix it? i want to use "/" ..

    help plz.

    um.. have nice day~ :)

     
  21. Michal says...

    @moondy2: sorry for that but there was a function missing within the class. There was a wrong version available ... please download the current version and it will work. greets michal

     
  22. Uri says...

    Thank you very much Michal!

    I'm so glad that there are people out there that develop for Classic ASP.
    your script really does saves time!
    and your site is now in my Fav's for sure :)

     
  23. Uri says...

    I have a question:

    i'm working with your code with recordsets. everything seems to work well..even records that are in hebrew, but dates.
    for some reason all the dates turned up like this:
    lastlogindate": "16\u002F05\u002F2007 16:51:32"
    any idea how to solve this?

     
  24. Michal says...

    hi uri, as your date has the following format 16/05/2007 it includes a solidus (/) which needs to be escaped due to the JSON specification. if you use e.g. Prototype (prototypejs.org) to parse the JSON output this will be parsed correctly.

     
  25. Bee says...

    Grammar != Grammer

     
  26. Uri says...

    hi michal, my situation is like this: im working with Ext.
    With your script I made an .asp file that takes my ms sql database puts it in a rs and writes it in a json format.
    and from the ext I make a grid that takes this date.

    where should I transform the sql date format into a json date format and how?

     
  27. michal says...

    you need to parse the JSON string first. i dont know the ext-library but ive found a JSON class http://extjs.com/deploy/ext/docs/output/Ext.util.JSON.html .. so after the XHR you should parse the response first

     
  28. Uri says...

    michal, thanks for your help.
    in the end i solved my problem by removing the procedure that checks for special chars in your script.
    because what I saw that Ext can handle special chars because the JsonReader is parsing the json code.

     
  29. oli says...

    Do you know any JSON parser ? JSON => ASP

     
  30. Uri says...

    Yeah, that would be nice!

     
  31. Marc says...

    JSON => ASP? like so:

    var json = {"widget":[{"value":"text here"},{"value":123}]};

    "
    Next
    Response.Write json.widget.[0].value
    %>

     
  32. Marc says...

    Let's try that again...

    <%@ Language=VBScript %>
    <script language="jscript" runat="server">
    var json = {"widget":[{"value":"text here"},{"value":123}]};
    </script>
    <%
    For Each o In json.widget
    Response.Write o.value & ""
    Next
    Response.Write json.widget.[0].value
    %>

     
  33. Mark Bajema says...

    Rather than lowercase all of the field names, I prefer camel-case so I changed line 126 to:

    toJSON lCase(left(val.fields(i).name, 1)) & right(val.fields(i).name, len(val.fields(i).name) - 1), val.fields(i).value, true

     
  34. Mark Bajema says...

    Declaring cDoubleQuote (const), cRevSolidus (const), cSolidus (const), i (dim), currDigit (dim) in the escape function as well as declaring i (dim) in a few other functions allows this script to run with "Option Explicit".

     
  35. CrayonCowboy Ranch » Parsing JSON With Classic ASP (VBScript) says...

    [...] I came across a post on the Web Dev Bros blog about Generating JSON from VBScript (ASP) datatypes. Along with the info in the post, Michal provided a download for a JSON utility class which will [...]

     
  36. Cliff says...

    Michal, your readers of this post might e interested in this post I just made about parsing JSON with VBScript.

    http://blog.crayoncowboy.com/?p=7

    Actually, its a VBScript class (free for private or commercial use) that allows you to easily parse JSON and get at the data from VBScript. Its got a few rough edges but I plan on ironing those out soon. Still, I'd like some feedback if anyone has any problems with it.

     
  37. Uri says...

    that some fine and helpful code!
    thank you very much Cliff and Michal!

     
  38. enotsl says...

    hi, i have some confuse of the function "getRecordset" at your examlp,

    how to get the data form database?

     
  39. Michal says...

    which example do you mean enotsl ?

     
  40. enotsl says...

    The first example

    ASP:
    set RS = getRecordset("SELECT * FROM table")
    response.write((new JSON).toJSON("rows", RS))

    the function "getRecordset"

    thanks!

     
  41. Michal says...

    the getRecordset is just an example how i query data from database. it needs to return an ADODB.recordset object ... which could look like this

    ASP:
    1. function getRecordset(sql)
    2.    set getRecordset = conn.execute(sql)
    3. end funciton

    'conn' must already hold an opened database connection.

     
  42. enotsl says...

    oh, i see, Thanks Michal

    and one more question, do you know how to transfer Json to asp array?

     
  43. Art says...

    I've been trying to use this library but it "chokes" (hangs and times out) any time I try to use it on a recordset of around 100 rows. I've tried it on the raw ADODB recordset and I've tried converting to an array using GetRows() but it doesn't make any difference.

    I have specified the property that makes the object write the JSON strings immediately rather than appending them.

    Has anyone else had problems like this?

     
  44. Brett says...

    I LOVE this utility, but I'm having trouble taking the next step. I can produce the JSON output OK, but when I try to use the generated data, nothing happens. I believe it has something to do with the "callback", but I can't find a VBScript example that I could use with the JSON.asp utility that would format the data properly for consumption by an EXT grid widget.

    Here's what I've tried:

    I've tried many different variations of this to no avail. I've even tried to replicate the data from their grid example on my local server and it just spins for a bit and returns no data even though when I compare the output from my test.asp script to the php script they use in the example they look identical.

    Any help would be appreciated!

    Keep up the good work!

     
  45. Cliff says...

    Brett,
    Just a few debugging tips...
    You're really dealing with two systems here:
    - ASP Creates JSON
    - Your (presumably JavaScript) widget generates a display based on JSON input.

    So you're going to first need to find the weak link.
    If it were me, I'd begin by trying whatever grid widget you're using and have it reference hand coded JSON data in a text file. If it works, you know it's a problem with your JSON output system. If it does not work, you can assume that the problem is possibly in the widget itself.

    The point is you need to break your troubleshooting down into smaller, easier to answer, questions.

    Also, if you're looking for help with a specific widget, it's probably helpful to provide a link to the widget you're using so anyone interested in helping can take a look & see what you're working with.

    First step is see if the widget works with correctly hand coded JSON. Good luck.

     
  46. Brett says...

    Thanks Cliff! I took your advice and it looks like the problem is with the widget, so I'll post my questions over there.

    I was trying to get the EXT grid widget to work. The documentation can be found at http://extjs.com/deploy/ext/docs/index.html. Navigate to Examples and Demos > Grid > Paging and Remote Datasets to see the specific example I'm trying to make work.

    I believe the JSON part is correct, so I'll focus my attention on the widget.

     
  47. Uri says...

    Hi Brett, I have experienced working with Michal's JSON.asp and Ext Js's Grid component with great success.
    I'll tell you how I worked with it, and maybe it will help you.
    First of all I recommend you to see the screencasts about editable grids (part II, but for background you should watch the first one as well - http://extjs.com/learn/Screencasts)

    I have a grid.js file that is basicly the whole grid mechanism. it retrives the grid's data from ajaxasp2.asp like this:

    function setupDataSource() {
    ds = new Ext.data.Store({
    proxy: new Ext.data.HttpProx({url:'ajaxasp2.asp'}),
    reader: new Ext.data.JsonReader(
    {root: 'data', id: 'itemid'},
    [
    {name: 'itemid', mapping: 'itemid'},
    {name: 'itemname', mapping: 'itemname'},
    {name: 'itempath', mapping: 'itempath'},
    {name: 'itemprice', mapping: 'itemprice'},
    {name: 'itemwidth', mapping: 'itemwidth'},
    {name: 'itemheight', mapping: 'itemheight'}
    ]
    )});
    ds.load();
    }

    aspajax2.asp has a very simple code in it. it basicly calls my MSSQL server, takes the data from the table and parse it to JSON (with Michal's great script):



    Now, Ext has it's own JSON parsing system, and Michal's code generates special chars for '\' etc.. My SQL's datetime looks like this 20/07/2007 so I had to remove the part that handle special chars from Michal's code. the escaping part...


    public function escape(val)
    cDoubleQuote = &h22
    cRevSolidus = &h5C
    cSolidus = &h2F

    for i = 1 to (len(val))
    currentDigit = mid(val, i, 1)
    if asc(currentDigit) > &h00 and asc(currentDigit) = &hC280 and asc(currentDigit) = &hC380 and asc(currentDigit)

    That's it....
    I hope it helped

     
  48. Uri says...

    hmmm... i don't know what happen to the code so i'll try again:

    ajaxasp2.asp looks lik that:


    and i disabled the following lines from JSON.asp:

    ' elseif asc(currentDigit) >= &hC280 and asc(currentDigit) = &hC380 and asc(currentDigit)

     
  49. Uri says...

    well i see what went wrong...i hope this time it will work:

    Response.ContentType = "text/html; charset=windows-1255"
    Set rs=Server.CreateObject("ADODB.RecordSet")
    rs.Open "SELECT * FROM ItemList",conn,3,3
    response.write((new JSON).toJSON("data", rs, false))

     
  50. Michal says...

    hey guys i have updated the class a bit. Now its possible to support your own custom classes. Implement a reflect() method and then its possible to access your objects within JavaScript. Works very nice!! Thanks to Cliff!

     
  51. Uri says...

    can you elaborate? maybe an example?
    Thanks,
    - Uri

     
  52. michal says...

    @Uri the examples are in the post .. i have updated it

     
  53. Rene says...

    I can´t figure out how to build this structure from a recordset:

    [
    {"text": "A","id": "A","cls": "folder", "children":
    [
    {"id": 31704,"text": "Anker","leaf": true,"cls": "file"},
    {"id": 31600,"text": "Auto","leaf": true,"cls": "file"}
    ]
    },
    {"text": "B","id": "B","cls": "folder", "children":
    [
    {"id": 31804,"text": "Baum","leaf": true,"cls": "file"},
    {"id": 32587,"text": "Box","leaf": true,"cls": "file"}
    ]
    },
    ]

     
  54. Michal says...

    @rene: this structure is not really possible out-of-the-box by the JSON generator. the recordset is parsed in a different way

     
  55. Michal says...

    hi JSON interested guys .. i have written a small ajax library for classic ASP .. you might be intereste. have a read on the first tutorial here:
    http://www.webdevbros.net/2007/07/02/ajaxed-calling-server-side-vbscript-procedures-from-client-side-equivalent-to-php-xajax/

     
  56. Media*A says...

    And here you can find how to READ JSON from ASP :)
    http://bigblog.mediaa.be/?p=3

     
  57. Cliff says...

    Media*A : Nice tip but that's not really reading JSON with ASP. That just illustrates the process of using the Microsoft.XMLHTTP object on the server side to fetch content, it wont really do anything but pass the JASON off to client side JavaScript. It's still useful though.

     
  58. Randy says...

    NESTED DICTIONARIES BREAK IT!!

    This was noted by Cliff a ways down in the comments and I am having the same problem. The only thing that is output is:

    }}

    Can you please fix this?!! I would love to use it, but I use nested dictionaries a lot!

     
  59. Randy says...

    The nested dictionary problem was being caused by the way you are doing your recursion. When the nested dictionary finishes, it sets recursiveGenerationCall = false, which in turn causes output to be set to an empty string. The fix is to make only the final dictionary set recursiveGenerationCall = false, which I implemented with a stack counter. However, the whole problem is really being caused by the way you are doing your recursion. Rather than using write(), you should be returning the string from toJson() and then concatenating that string to the current output all the way back through the recursion process.

    Anyway, here is my fix:

    line 22: private output, recursiveGenerationCall, dicStack
    line 33: dicStack = 0
    line 115 (and following):
    elseif typename(val) = "Dictionary" then
    if dicStack = 0 then
    recursiveGenerationCall = true
    end if
    dicStack = dicStack + 1
    write("{")
    keys = val.keys
    for i = 0 to uBound(keys)
    if i > 0 then write(",")
    toJSON keys(i), val(keys(i)), true
    next
    write("}")
    dicStack = dicStack - 1
    if dicStack = 0 then
    recursiveGenerationCall = false
    end if
    elseif typename(val) = "Recordset" then

     
  60. Cliff says...

    To be honest, I've never seen the need or usefulness of the recursiveGenerationCall flag. I think the finction can determine wether its recursive or not on its own based on data type without needing a variable to hold a status indicator. I'd provided a modified version that handled recursion a bit differently, and is a bit more "all-purpose" that the current version. Granted it amounts to a pretty significant deviation from the original class, but I find it preferable since it applies to any data type that can possibly handle recursion (including custom classes). Michal has the modified version if its of any use in the future.

     
  61. Randy says...

    Cliff,

    Can you please send me your version? My email:

    randy@rcs-comp.remove-spam.com

    remove '.remove-spam' (but you probably figured that out).

    Thanks.

     
  62. Brian Ackermann says...

    Hi all!

    I've been playing with this handy utility since yesterday, and I've come across a small hitch. I to am using this tool to fill an EXT grid control. For the basic grid, I had no problems whatsoever. But now I wish to impliment a pager for the grid, and so I need to add a property to the root of the json, but can't think how to do it.

    Basically, I need this:

    {
    "total":"125",
    "rows": [ { "id": 65,"username": "Wmensen" }
    ,{ "id": 101,"username": "etc...." }
    ]
    }

    But I can't for the life of me think how to insert the "total" property into the results neatly.

    I suppose I could simply parse the string, add the property, and re-assemble, but that seems silly.

    What would the 'RIGHT' way to do this be?

    Brian

     
  63. Cliff says...

    Randy,
    I have no objection to you using my code, but this is Michal's project and my version is quite a bit different in some ways. I'd much rather have him maintain control of the project without stepping on his toes. :-)

    He does have the last version I put together so you're more than welcome to contact him & request it. He's incorporated the ability to serialize ("reflect" I believe is his method name) custom classes so maybe some of the other options will make their way in as well. I'd love to see some of the other additions from my version like supporting Session, Application, and Request collections.

    Anyway, hope it's not rude to keep my version under wraps, but its Michal's project & it really should go through him.

     
  64. michal says...

    Hi brian, in order to achieve this structure i would put the following code into a seperate page:

    ASP:
    1. <!--#include file="JSON.asp"-->
    2. <%
    3. set j = new JSON
    4. j.toResponse = true
    5. with response
    6.     .write("{")
    7.     j.toJSON "total", 125, true
    8.     .write(",")
    9.     j.toJSON "rows", array(1, 2, 3, 4), true
    10.     .write("}")
    11. end with
    12. %>

    You could achieve the same also with "toResponse = false" by concatenating the string ... but this is nicer and also much faster. The whole trick here is that you mark your two name-value-pairs as already nested (third parameter of the toJSON method).

     
  65. Michal says...

    @Randy and NESTED DICTIONARIES: could you please show your code where you use nested dictionaries? because for me its working fine ... check the following example:

    ASP:
    1. set j = new JSON
    2. j.toResponse = true
    3.  
    4. set d = server.createObject("scripting.dictionary")
    5. d.add "d-1-1", "something"
    6. set d2 = server.createObject("scripting.dictionary")
    7. d2.add "d-2-1", "hello"
    8. d2.add "d-2-2", true
    9. d.add "d-1-2", d2
    10.  
    11. j.toJSON empty, d, false

    you could also name the dictionary and then also able to control the "nested" argument. The "recursiveGenerationCall" indicates that the call of toJSON has been made internally and not by the client outside. Maybe the naming is a bit bad ;) but this flag is indeed necessary when you use the toJSON method more than once...

     
  66. Uri says...

    Hi Michal,

    I need to get a JSON string to look like this:


    {"NAME": "misc.jpg","SIZE": 87832,"TYPE": "JPEG Image","DTS": "16/07/2007 16:55:54","FILEURL": "../dim/day/misc.jpg","FILEEXISTED": "NO"}

    meaning without the root name and its brackets.
    how do I do so?

     
  67. Uri says...

    nevermind, i solved it...

     
  68. Uri says...

    Hey Michal,

    I was thinking that maybe the ability to print a single string, eg:


    {"NAME": "misc.jpg","SIZE": 87832,"TYPE": "JPEG Image","DTS": "16/07/2007 16:55:54","FILEURL": "../dim/day/misc.jpg","FILEEXISTED": "NO"}

    should be in the class. the way I did it is when i give the json the name "remove"


    response.write((new JSON).toJSON("remove", oRS, false))

    it doesn't add the [] part...
    I can send you the code, but I guess you don't need it.

    and another thing, from my experience - working with your JSON parsing and Ext, the escaping part is making problems, espacialy with dates.
    so maybe the escaping should be called only if the user wants it, with a boolean arg or something.

    just a thought :)

     
  69. Michal says...

    hi uri ... its not very wise to include more methods like remove, etc. You should try to come with the right data structure / data type in order to produce the right JSON. The approach of manipulating the JSON output is not good. Show me your code (incl the wanted JSON) and we can think of how to manipulate your input that it fits. Every kind of JSON should be possible with the current version.

    @EXT escaping problem: i always wanted to check the ext library but had no time yet. Will check this and decide how this affects the JSON class. A flag which turns on/off the escaping sound good btw.

     
  70. Uri says...

    Hi Michal,

    I'm working on the Ext UploadDialog Widget. Making it Classic ASP...

    It uses JSON data in 2 places, one in showing the files in the upload dir. which is a regular JSON, which was done with the JSON class easily.

    and the other spot is to add a new file. the script works like this:
    the user adds the file in the form (input type="file") and then in the server side script it uploads the file and returns a JSON string that need to look like this:


    {"NAME": "misc.jpg","SIZE": 87832,"TYPE": "JPEG Image","DTS": "16/07/2007 16:55:54","FILEURL": "../dim/day/misc.jpg","FILEEXISTED": "NO"}

    with this information the Ext UploadDialog knows which file was edited, if it's a new one it will add a new row and if not it will just update the information.

    the full Ext code can be found in the link above.

     
  71. michal says...

    uri you can easily do this the following way:
    1) create a page which does the upload (maybe a parameter for new/existing)
    2) when the upload is finished you can return a dictionary the following way:

    ASP:
    1. <!--#include file="json.asp"-->
    2. <%
    3. set j = new JSON
    4. j.toResponse = true
    5. set d = server.createObject("scripting.dictionary")
    6. with d
    7.     .add "NAME", "misc.jpg"
    8.     .add "SIZE", 87832
    9.     .add "TYPE", "JPEG Image"
    10.     '....
    11. end with
    12. j.toJSON empty, d, false
    13. %>

    this will return you the desired JSON output.

     
  72. Uri says...

    ohh thanks Michal!

    I didn't know that with Dicionary I can achive what I needed

     
  73. Randy says...

    Concerning the nested dictionaries, this code outputs "}}":

     
  74. Randy says...

    Lets try this again: the code that caused dictionary problems:

    <!--#include file="JSON.asp"-->
    <%
    Dim dicMain, dicSub
    set dicMain = Server.CreateObject("Scripting.Dictionary")
    set dicSub = Server.CreateObject("Scripting.Dictionary")

    dicSub.add 1.1, true

    dicMain.add 1, dicSub

    dim sOutput
    sOutput = (new JSON).toJSON("data", dicMain, false)
    response.write sOutput

    %>

     
  75. Michal says...

    Hi Randy, thanks for your snippet. I found the problem now. It was only working directly to the response ... thats why I never experienced it because i usually let the JSON generator output directly to the response.
    I solved it in a similar way you posted it once (stackcounter) but i also removed the recursiveGenerationCall flag.
    I also did some small refactoring and added support for currency and byte.

     
  76. Randy says...

    Thanks!

     
  77. Randy says...

    One last thing. The class does not work when OPTION EXPLICIT has been declared. Can you update that?

     
  78. Uri says...

    Hey Michal,

    Just wanted to say that the Dicionary solution for my problem worked smoothly.

    Thanks!

     
  79. FUSiON says...

    Hi,

    in your actual version i missed a support for 2 dimensional arrays.
    Here is my solution:


    '******************************************************************************************************************
    '* proof array dimension
    '******************************************************************************************************************
    function isArrayMulti(inArray)
    isArrayMulti = false
    on error resume next
    dim tmpVar
    tmpVar = inArray(0, 0)

    if err.number = 0 then
    'the array is useable...
    isArrayMulti = true
    end if
    end function

    '*************************************************************************************************