JSON character escaping function in classic ASP

If you are into advanced AJAX techniques you probably will stumble across JSON (www.json.org) which makes developing (and therefore the life) a lot easier when working with AJAX. If you already stumbled across and you use JSON within classic ASP you might find this article useful. It deals with escaping characters for JSON acording to the RFC4627#2.5

I haven't found any snippet out there for classic ASP so we had to write our own. And so my work colleague - an old algorithm guru - just came up with this function which covers all the requirements specified in the JSON RFC.

What we want to achieve...

ASP:
  1. <script>
  2.   alert({foo:"<%= "some va""lue" %>"}.foo);
  3. </script>

The code snippet above will result in a javascript error because we are passing an apostrophe from ASP to Javascript which leads to an early closing of the string: foo:"some va"lue" (there is one apostrophe too much). The same thing happens for other characters as well. If you have line breaks, german umlaute, hidden special characters, etc. All those need to be escaped now in order that the javascript simple object notation (JSON) can interpret it. Thats the function which does the escaping (there are 3 more functions cause they're used within the escapeJSON()):

ASP:
  1. '******************************************************************************************
  2. '' @SDESCRIPTION:   takes a given string and makes it JSON valid (http://json.org/)
  3. '' @AUTHOR: Michael Rebec
  4. '' @DESCRIPTION:    all characters which needs to be escaped are beeing replaced by their
  5. ''          unicode representation according to the
  6. ''          RFC4627#2.5 - http://www.ietf.org/rfc/rfc4627.txt?number=4627
  7. '' @PARAM:      val [string]: value which should be escaped
  8. '' @RETURN:   [string] JSON valid string
  9. '******************************************************************************************
  10. public function escapeJSON(val)
  11.     cDoubleQuote = &h22
  12.     cRevSolidus = &h5C
  13.     cSolidus = &h2F
  14.    
  15.     for i = 1 to (len(val))
  16.         currentDigit = mid(val, i, 1)
  17.         if asc(currentDigit)> &h00 and asc(currentDigit) <&h1F then
  18.             currentDigit = escapeJSONSquence(currentDigit)
  19.         elseif asc(currentDigit)>= &hC280 and asc(currentDigit) <= &hC2BF then
  20.             currentDigit = "\u00" + right(padLeft(hex(asc(currentDigit) - &hC200), 2, 0), 2)
  21.         elseif asc(currentDigit)>= &hC380 and asc(currentDigit) <= &hC3BF then
  22.             currentDigit = "\u00" + right(padLeft(hex(asc(currentDigit) - &hC2C0), 2, 0), 2)
  23.         else
  24.             select case asc(currentDigit)
  25.                 case cDoubleQuote: currentDigit = escapeJSONSquence(currentDigit)
  26.                 case cRevSolidus: currentDigit = escapeJSONSquence(currentDigit)
  27.                 case cSolidus: currentDigit = escapeJSONSquence(currentDigit)
  28.             end select
  29.         end if
  30.         escapeJSON = escapeJSON & currentDigit
  31.     next
  32. end function
  33.  
  34. function escapeJSONSquence(digit)
  35.     escapeJSONSquence = "\u00" + right(padLeft(hex(asc(digit)), 2, 0), 2)
  36. end function 
  37.  
  38. function padLeft(value, totalLength, paddingChar)
  39.     padLeft = right(clone(paddingChar, totalLength) & value, totalLength)
  40. end function
  41.  
  42. public function clone(byVal str, n)
  43.     for i = 1 to n : clone = clone & str : next
  44. end function

So now we should be able to escape the strings for JSON like this and no error should occur...

ASP:
  1. <script>
  2.   alert({foo:"<%= escapeJSON("some va""lue") %>"}.foo);
  3. </script>

This stuff has been tested and works for all characters so everything can be transfered with JSON now ;) I would suggest to group the whole functions into a class called JSON with a method escape() just for a nicer use. In my case its in a utility class StringOperations where I have several string manipulation methods. If you are interested you can download the full String class also which include the JSON escaping method:

StringOperations 0.9 (StringOperations Documentation)


1 Star2 Stars3 Stars4 Stars5 Stars (16 votes, average: 4.06 out of 5)
Loading ... Loading ...

5 Comments

  1. amol says:

    Thanks a ton! I was going crazy coz wasn't finding one suitable solution for ASP. Thanks again!

  2. Erik says:

    Hi Michal,

    I'm having a problem converting the string back to special characters. When I get data from JSON and the strings are escaped, and I need to put that data into a form field the \uuxx numbers are still there instead of the special characters. Do you have, or know of any function that reverses this process?

    Erik

  3. Emtucifor says:

    I rate this code: FLUNK.

    Your code:
    - Escapes characters unnecessarily (such as forward slash).
    - Escapes using more characters than needed, making the JSON longer (using hex notation instead of simple backslash-escaping).
    - Escapes every high Ascii character as \u00__ which is not only longer than \x__ but completely ignores the first byte of Unicode characters, making the result meaningless.
    - Has goofy stuff like "- &hC2C0" which is clearly an undefined operation to perform on Unicode between &hC380 and &hC3BF. Perhaps you're matching character sets to character sets, but this is something you're supposed to solve with fonts, not subtraction to turn one code into another. To make your preposterous claim "This stuff has been tested and works for all characters so everything can be transfered with JSON now" valid, you have to rip out this junk. I don't care how elaborate a character map you use, you'll still be altering characters, hardly the desire of most people who want to send Unicode characters through JSON from ASP.

    Here is my version:

    [asp]Function JSONEscape(json)
    Dim Pos
    Dim Char
    Dim Code
    JSONEscape = ""
    If IsNull(json) Then Exit Function
    For Pos = 1 To Len(json)
    Char = Mid(json, Pos, 1)
    Code = AscW(Char)
    If (Code >= 32 And Code <= 127) And Code 34 And Code 39 And Code 60 And Code 92 Then 'printable, plus skip '"\ and to avoid false HTML tags 0 Then
    JSONEscape = JSONEscape & "\" & VBA.Mid("bfnOrtv'""\", Code, 1)
    Else
    Code = AscW(Char)
    If (Code >= 0 And Code <= 255) Then 'escape nonprinting, high ascii, and < characters (to avoid false HTML tags)'
    JSONEscape = JSONEscape & "\x" & VBA.Right("0" & Hex(Code), 2)
    Else
    JSONEscape = JSONEscape & "\u" & VBA.Right("000" & Hex(Code), 4)
    End If
    End If
    End If
    Next
    End Function[/as]

  4. Emtucifor says:

    For want of a preview function, a p was lost :) ...

    ASP:
    1. Function JSONEscape(json)
    2.    Dim Pos
    3.    Dim Char
    4.    Dim Code
    5.    JSONEscape = ""
    6.     If IsNull(json) Then Exit Function
    7.    For Pos = 1 To Len(json)
    8.       Char = Mid(json, Pos, 1)
    9.       Code = AscW(Char)
    10.       If (Code&gt;= 32 And Code &lt;= 127) And Code  34 And Code  39 And Code  60 And Code  92 Then 'printable, plus skip '"\ and to avoid false HTML tags  0 Then
    11.             JSONEscape = JSONEscape &amp; "\" &amp; VBA.Mid("bfnOrtv'""\", Code, 1)
    12.          Else
    13.             Code = AscW(Char)
    14.             If (Code&gt;= 0 And Code &lt;= 255) Then 'escape nonprinting, high ascii, and &lt;characters (to avoid false HTML tags)'
    15.                JSONEscape = JSONEscape &amp; "\x" &amp; VBA.Right("0" &amp; Hex(Code), 2)
    16.             Else
    17.                JSONEscape = JSONEscape &amp; "\u" &amp; VBA.Right("000" &amp; Hex(Code), 4)
    18.             End If
    19.          End If
    20.       End If
    21.    Next
    22. End Function

  5. Emtucifor says:

    And the second comment in the last If statement should be removed. It is a leftover after reordering the code to hit most likely conditions first in the loop.

Leave a Reply