json.asp


<%
'**********************************************************************************************
'* GAB_LIBRARY Copyright (C) 2003 - This file is part of GAB_LIBRARY       
'* For license refer to the license.txt                                       
'***********************************************************************************************

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

'' @CLASSTITLE:        JSON
'' @CREATOR:        Michal Gabrukiewicz (gabru at grafix.at), Michael Rebec
'' @CONTRIBUTORS:    - Cliff Pruitt (opensource at crayoncowboy.com)
''                    - Sylvain Lafontaine
'' @CREATEDON:        2007-04-26 12:46
'' @CDESCRIPTION:    Comes up with functionality for JSON (http://json.org) to use within ASP.
''                     Correct escaping of characters, generating JSON Grammer out of ASP datatypes and structures
'' @REQUIRES:        -
'' @OPTIONEXPLICIT:    yes
'' @VERSION:        1.4

'****************************************************************************************
class JSON

'private members
private output, innerCall

'public members
public toResponse        ''[bool] should generated results be directly written to the response? default = false

'*********************************************************************************
'* constructor
'*********************************************************************************
public sub class_initialize()
        newGeneration()
        toResponse = false
end sub

'******************************************************************************************
'' @SDESCRIPTION:    STATIC! takes a given string and makes it JSON valid
'' @DESCRIPTION:    all characters which needs to be escaped are beeing replaced by their
''                    unicode representation according to the
''                    RFC4627#2.5 - http://www.ietf.org/rfc/rfc4627.txt?number=4627
'' @PARAM:            val [string]: value which should be escaped
'' @RETURN:            [string] JSON valid string
'' asc 函数被替换成ascw函数以便支持中文
'******************************************************************************************
public function escape(val)
dim cDoubleQuote, cRevSolidus, cSolidus
        cDoubleQuote = &h22
        cRevSolidus = &h5C
        cSolidus = &h2F

dim i, currentDigit
for i = 1 to (len(val))
            currentDigit = mid(val, i, 1)
if ascw(currentDigit) > &h00 and ascw(currentDigit) < &h1F then
                currentDigit = escapequence(currentDigit)
elseif ascw(currentDigit) >= &hC280 and ascw(currentDigit) <= &hC2BF then
                currentDigit = "\u00" + right(padLeft(hex(asc(currentDigit) - &hC200), 2, 0), 2)
elseif ascw(currentDigit) >= &hC380 and ascw(currentDigit) <= &hC3BF then
                currentDigit = "\u00" + right(padLeft(hex(ascw(currentDigit) - &hC2C0), 2, 0), 2)
else
select case ascw(currentDigit)
case cDoubleQuote: currentDigit = escapequence(currentDigit)
case cRevSolidus: currentDigit = escapequence(currentDigit)
case cSolidus: currentDigit = escapequence(currentDigit)
end select
end if
            escape = escape & currentDigit
next
end function

'******************************************************************************
'' @SDESCRIPTION:    generates a representation of a name value pair in JSON grammer
'' @DESCRIPTION:    the generation is done fully recursive so the value can be a complex datatype as well. e.g.
''                    toJSON("n", array(array(), 2, true), false) or toJSON("n", array(RS, dict, false), false), etc.
'' @PARAM:            name [string]: name of the value (accessible with javascript afterwards). leave empty to get just the value
'' @PARAM:            val [variant], [int], [float], [array], [object], [dictionary], [recordset]: value which needs
''                    to be generated. Conversation of the data types (ASP datatype -> Javascript datatype):
''                    NOTHING, NULL -> null, ARRAY -> array, BOOL -> bool, OBJECT -> name of the type,
''                    MULTIDIMENSIONAL ARRAY -> generates a 1 dimensional array (flat) with all values of the multidim array
''                    DICTIONARY -> valuepairs. each key is accessible as property afterwards
''                    RECORDSET -> array where each row of the recordset represents a field in the array.
''                    fields have properties named after the column names of the recordset (LOWERCASED!)
''                    e.g. generate(RS) can be used afterwards r[0].ID
''                    INT, FLOAT -> number
''                    OBJECT with reflect() method -> returned as object which can be used within JavaScript
'' @PARAM:            nested [bool]: is the value pair already nested within another? if yes then the {} are left out.
'' @RETURN:            [string] returns a JSON representation of the given name value pair
''                    (if toResponse is on then the return is written directly to the response and nothing is returned)
'*******************************************************************************************
public function toJSON(name, val, nested)
if not nested and not isEmpty(name) then write("{")
if not isEmpty(name) then write("""" & escape(name) & """: ")
        generateValue(val)
if not nested and not isEmpty(name) then write("}")
        toJSON = output

if innerCall = 0 then newGeneration()
end function

'*********************************************************************************
'* generate
'******************************************************************************
private function generateValue(val)
if isNull(val) then
            write("null")
elseif isArray(val) then
            generateArray(val)
elseif isObject(val) then
if val is nothing then
                write("null")
elseif typename(val) = "Dictionary" then
                generateDictionary(val)
elseif typename(val) = "Recordset" then
                generateRecordset(val)
else
                generateObject(val)
end if
else
'bool
            varTyp = varType(val)
if varTyp = 11 then
if val then write("true") else write("false")
'int, long, byte
elseif varTyp = 2 or varTyp = 3 or varTyp = 17 or varTyp = 19 then
                write(cLng(val))
'single, double, currency
elseif varTyp = 4 or varTyp = 5 or varTyp = 6 or varTyp = 14 then
                write(replace(cDbl(val), ",", "."))
else
                write("""" & escape(val & "") & """")
end if
end if
        generateValue = output
end function

'*****************************************************************************
'* generateArray
'*****************************************************************************
private sub generateArray(val)
dim item, i
        write("[")
        i = 0
'the for each allows us to support also multi dimensional arrays
for each item in val
if i > 0 then write(",")
            generateValue(item)
            i = i + 1
next
        write("]")
end sub

'*********************************************************************************
'* generateDictionary
'**************************************************************************
private sub generateDictionary(val)
dim keys, i
        innerCall = innerCall + 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("}")
        innerCall = innerCall - 1
end sub

'*******************************************************************
'* generateRecordset
'*******************************************************************
private sub generateRecordset(val)
dim i
        write("[")
while not val.eof
            innerCall = innerCall + 1
            write("{")
for i = 0 to val.fields.count - 1
if i > 0 then write(",")
                toJSON lCase(val.fields(i).name), val.fields(i).value, true
next
            write("}")
            val.movenext()
if not val.eof then write(",")
            innerCall = innerCall - 1
wend
        write("]")
end sub

'*******************************************************************************
'* generateObject
'*******************************************************************************
private sub generateObject(val)
dim props
on error resume next
set props = val.reflect()
if err = 0 then
on error goto 0
            innerCall = innerCall + 1
            toJSON empty, props, true
            innerCall = innerCall - 1
else
on error goto 0
            write("""" & escape(typename(val)) & """")
end if
end sub

'*******************************************************************************
'* newGeneration
'*******************************************************************************
private sub newGeneration()
        output = empty
        innerCall = 0
end sub

'*******************************************************************************
'* JsonEscapeSquence
'*******************************************************************************
private function escapequence(digit)
        escapequence = "\u00" + right(padLeft(hex(asc(digit)), 2, 0), 2)
end function

'*****************************************************************************
'* padLeft
'*****************************************************************************
private function padLeft(value, totalLength, paddingChar)
        padLeft = right(clone(paddingChar, totalLength) & value, totalLength)
end function

'*****************************************************************************
'* clone
'******************************************************************************************
public function clone(byVal str, n)
dim i
for i = 1 to n : clone = clone & str : next
end function

'******************************************************************************************
'* write
'******************************************************************************************
private sub write(val)
if toResponse then
            response.write(val)
else
            output = output & val
end if
end sub

end class
%> 

使用案例:



<%@LANGUAGE="VBSCRIPT" CODEPAGE="65001"%>
<% Response.Addheader "Content-Type","text/html; charset=utf-8"  %>
<!--#include file="inc/json.asp"-->
<!--#include file="inc/Conn.asp" -->
<%
'response.ContentType="text/json"
dim j

'多重嵌套的JSON,要使用Dictionary才能实现
set j=new json
j.toResponse=false
set r=server.createobject("scripting.dictionary")
set b=server.createobject("scripting.dictionary")
set c=server.createobject("scripting.dictionary")
                            c.add "x",5
                            c.add "y",6
                            c.add "z",11
                b.add "event","Mouse Click"
                b.add "data",c
r.add "success",true
r.add "result",b
a=j.toJSON(empty,r,false)
'response.write a
%>

<%
    Dim sql_class,sql_top,sql_colums,sql_whereBy,sql_orderBy
    sql_class = request.Item("sql_class")
    sql_top = request.Item("sql_top")
    sql_colums = request.Item("sql_colums")
    sql_whereBy = request.Item("sql_whereBy")
    sql_orderBy = request.Item("sql_orderBy")

    Sql="select "&sql_top&" "&sql_colums&" from "&sql_class&" where 1=1 "&sql_whereBy&" "&sql_orderBy
%>

<%
    Set Rs = Server.CreateObject("ADODB.Recordset")      
    Rs.Open sql,conn,1,3 
    jsonStr = ""
    rows = ""

    Dim i,json_rows,json_ret,arr_rows
    Dim myArray()
    Redim myArray(rs.recordcount-1) '将数组大小重新定义为20
    Set jsonObj=New json
    jsonObj.toResponse=False
    Set json_ret = server.createobject("scripting.dictionary")        
    For i=0 To rs.recordcount-1
        Set myArray(i) = server.createobject("scripting.dictionary")
        For Each e In rs.Fields                
                'rows = rows &""""& e.Name & """:""" & replace(e.value,chr(34),"@_'_@") & """," 
                myArray(i).Add e.Name,e.value  '将key/value加到行数组对象中
        Next   
        Rs.movenext
    Next       
    json_ret.Add "total",rs.recordcount
    json_ret.Add "rows",myArray 
    jsonStr = jsonObj.toJSON(Empty,json_ret,False)

    response.Write jsonStr

%>

asp输出json对象实例