经典ASP:如何使用AX json实现将RecordSet转换为json表示法

时间:2012-02-17 17:41:17

标签: javascript json asp-classic vbscript jscript

我正在使用jQuery和其他一些工具使用ajax进行应用程序,并且在某些方面我想使用经典的ASP后端使用ajax检索数据,我看到在AX中存在一个很好的JSON类实现(Asp极端版)框架,我用它但目前我不明白如何使用它。

修改:根据JSON.Stringify fails on Scripting.Dictionary objects主题的正确答案,我决定制作一个自定义函数来处理Recordsets。

编辑2:现在,在函数JSONStringify(object)中调用 JSON.stringify 时,我正在丢失值数据。

当Recordset作为值传递给 JSONStringify 时一切正常但是当 JSON.stringify 执行时,“ value ”参数表示必须包含记录集变为 undefined

我期待什么(例子)

从SQL查询SELECT name, tel FROM users传递一个Recordset,看看像这样的输出

[
    {"name":"Jonh Smith", "tel":"12345678"},
    {"name":"April Michelson", "tel":"77788802"},
    ...
]

传递一个字典,并根据字典中声明的元素查看类似内容。

{
   "element1":"value1",
   "element2":"value2",
   "element3":"value3",
   "element4":"value4",
   "element5":"value5"
}

如果我想支持其他类型的对象,我可以扩展功能

源代码

getcatalogos.asp

<!--#include file="../includes/conexion.asp" -->
<!--#include file="../includes/json2.asp" -->
<!--#include file="../includes/json-stringify-parser.asp" -->
<%
Response.ContentType = "application/json"
dim aVals(2)

function getCatalogo(tipo, params)
    Dim oConn,oCmd,sSQL,oRs,cont2
    Dim aData,oPar,cont
    dim Info 

    set oConn = Server.CreateObject("ADODB.Connection")
    set oCmd = Server.CreateObject("ADODB.Command")

    sWhere = ""

    oConn.ConnectionString = strcon
    oConn.Open
    Set oCmd.ActiveConnection = oConn

    select case tipo
        case "g"
            sSQL = " SELECT cve_gr, descr FROM gr ORDER BY descr ;"
        case "z" 
            sSQL = " SELECT cve_zn, descr FROM zn WHERE cve_gr = ? ORDER BY descr ;"
            if IsArray(params) Then
                Set oPar=oCmd.CreateParameter (params(0),129,1,2,params(1))
                oCmd.Parameters.Append(oPar)
            End if
        case else
            getCatalogo = false
            exit function
    end select

    oCmd.CommandText = sSQL
    Set oRs = oCmd.Execute()
    if Not oRs.EOF Then
        response.write(JSONStringify(oRs))
        getCatalogo = true
    else
        getCatalogo = false
    end if
    oConn.Close
end function

aVals(0) = "cve_gr"
aVals(1) = request.querystring("gr")
if Not getCatalogo(request.querystring("t"),aVals) Then
    %>error<%
end if

%>

JSON-字符串化-parser.asp

<!--#include file="vbsTyper.asp" -->
<script runat="server" language="JScript">

    function JSONStringify(object) {
        VBSTypeName(object);
        return JSON.stringify(object,stringifyData);
    }

    function stringifyData(holder, key, value) {
        var sType = '';
        var result;

        //response.write('pre...holder=' + holder + ',key=' + key + ',value=' + value);
        sType = VBSTypeName(value);
        //response.write('post =' + sType);

        //response.write(sType);
        switch(sType){
            case 'Dictionary':
                result = '{';
                for(var enr = new Enumerator(value); !enr.atEnd(); enr.moveNext()){
                    key = enr.item();
                    result += '"' + key + '": ' + JSON.stringify(value.Item(key));
                };
                result += '}';
                return(result);
                break;
            case 'Recordset':
                response.write('here!!!');
                var sTemp = '';
                result = '{';
                while(!value.EOF){
                    if(Len(result) > 0){
                        result += ',';
                    }
                    result += '{';
                    for (var i = value.Fields.Count - 1; i >= 0; i--){
                        if(len(sTemp) > 0){
                            sTemp += ',';
                        }
                        sTemp += '"' + value.Fields(i).name + '":' + JSON.stringify( value.Fields(i).value);
                    };
                    result += '}';
                }   
                result += '}';
                return result;
                break;
            default:
                //response.write(sType);
                return(value);
        }     
        // return the value to let it be processed in the usual way
        return result;
   }

</script>

vbsTyper.asp

<%
Function VBSTypeName(Obj)
    dim sType 
    sType = Cstr(TypeName(Obj))
    response.write(sType)
    VBSTypeName = sType
End Function
%>

2 个答案:

答案 0 :(得分:2)

此:

response.write(JSON.stringify(oRs))

应该是这样的:

Do Until oRS.EOF
  response.write(JSON.stringify(oRs("cve_gr") & ":" & oRs("descr"))
  oRS.MoveNext
Loop

答案 1 :(得分:1)

实现它......

简短版本:我不得不修改json2.asp并破解stringify()函数定义以使其正常工作。

长版

稍后会查看每行代码并放弃问题。我决定查看json2.asp(AX框架)并试着看看它在那里发生了什么。

看看我看到了什么:

screenshot of json2.asp source code

从第682行到第687行,如果找到自定义的字符串解析器但后来没有做任何事情则验证...仅返回Object值。

这里有猜测,因为我不太了解每个Javascript实现是如何工作的,但是暗示原始代码运行良好,是一个标准的javascript解释器(读取其他所有内容但是microsoft here )将在此sutuation中强制对象进行序列化,但JScript解释器尝试解析对象并将值传递为 null 。导致使用自定义stringyfier的每个函数都无法读取函数中传递的对象。

我做了什么来解决确定我在第688行之前插入了这段代码,强制执行自定义stringyfier,其值直接作为参数传递,避免了隐式解析。

        // Hack & patch to deliver the stringify-ing of the object correctly
        // IDK if this is CORRECT or dont but it works in VbScript
        if(replacer){
            var textval = rep(this,'',value);
            value = textval;
        }

后来我不得不在 json-stringify-parser.asp 中做一些更改,因为我必须修复导致此代码的一些错误

<!--#include file="vbsTyper.asp" -->
<script runat="server" language="JScript">

    function JSONStringify(object) {
        //VBSTypeName(object);
        return JSON.stringify(object,stringifyData,4);
    }

    function stringifyData(holder, key, value) {
        var sType = '';
        var result;

        //response.write('pre...holder=' + holder + ',key=' + key + ',value=' + value);
        sType = VBSTypeName(value);
        //response.write('post =' + sType);

        //response.write(sType);
        switch(sType){
            case 'Dictionary':
                result = '{';
                for(var enr = new Enumerator(value); !enr.atEnd(); enr.moveNext()){
                    key = enr.item();
                    result += '"' + key + '": ' + JSON.stringify(value.Item(key));
                };
                result += '}';
                return(result);
                break;
            case 'Recordset':
                //response.write('here!!!');
                var sTemp;
                result = '';
                while(!value.EOF){
                    if(result.length > 0){
                        result += ',';
                    }
                    result += '{';
                    sTemp=''
                    for (var i = 0; i < value.fields.Count; i++){
                        if(sTemp.length > 0){
                            sTemp += ',';
                        }
                        //response.write("i=" + i + ",");
                        sTemp += '"' + value.fields.item(i).name + '":' + JSON.stringify( value.fields.item(i).value);
                    };
                    result += sTemp + '}';
                    value.moveNext();
                }   
                result = '{' + result  + '}';
                return result;
                break;
            default:
                //response.write(sType);
                return(value);
        }     
        // return the value to let it be processed in the usual way
        return result;
   }

</script>

解析Recordset的部分有效,解析字典的部分与JSON.Stringify fails on Scripting.Dictionary objects中显示的部分相同(a.k.a。我还没有测试过)但是现在我已经完成了这个。

使用记录集对象测试我的更改会产生此输出

"{
    {\"clave\":\"BC\",\"descripcion\":\"Cal\"},
    {\"clave\":\"CT\",\"descripcion\":\"Center\"},
    {\"clave\":\"NE\",\"descripcion\":\"Norw\"},
    {\"clave\":\"NO\",\"descripcion\":\"Nore\"},
    {\"clave\":\"NT\",\"descripcion\":\"North\"},
    {\"clave\":\"OC\",\"descripcion\":\"East\"},
    {\"clave\":\"OR\",\"descripcion\":\"West\"},
    {\"clave\":\"PE\",\"descripcion\":\"Pen\"},
    {\"clave\":\"SE\",\"descripcion\":\"Southe\"},
    {\"clave\":\"ZM\",\"descripcion\":\"Met\"}
}"

问题留下

我留下的问题就是黑客攻击。

  • 输出在初始化时具有(“)字符,这是可以的 结束,我还有其他一切都有逃避传感器?或者是它的东西 这不应该发生。

  • 这种黑客行为真的是错误的...我可以做得更好,在此 那种情况?

  • 我的结论或论点出了点问题?