gpt4 book ai didi

javascript - JSON.Stringify 在 Scripting.Dictionary 对象上失败

转载 作者:行者123 更新时间:2023-11-29 17:30:07 26 4
gpt4 key购买 nike

我正在开发一个 ASP 经典项目,我在其中实现了找到的 JScript JSON 类 here .它能够与 VBScript 和 JScript 互操作,并且几乎与 json.org 中提供的代码完全相同。 .我的团队经理要求我为此项目使用 VBScript。

它在 ASP 中定义的基元和类上工作得很好。但我需要 Dictionary 对象,据我所知,这些对象只能通过 COM 互操作获得。 (通过 Server.CreateObject("Scripting.Dictionary"))我有以下代表产品的类:(ProductInfo.class.asp)

<%
Class ProductInfo

Public ID
Public Category
Public PriceUS
Public PriceCA
Public Name
Public SKU
Public Overview
Public Features
Public Specs

End Class
%>

Specs 属性是键值对的字典。以下是我对其进行序列化的方式:(product.asp)

<%
dim oProd
set oProd = new ProductInfo
' ... fill in properties
' ... output appropriate headers and stuff
Response.write( JSON.stringify( oProd ) )
%>

当我将 ProductInfo 的实例传递给 JSON.Stringify 时(如上所示),我得到如下内容:

{
"id": "1547",
"Category": {
"id": 101,
"Name": "Category Name",
"AlternateName": "",
"URL": "/category_name/",
"ParentCategoryID": 21
},
"PriceUS": 9.99,
"PriceCA": 11.99,
"Name": "Product Name",
"SKU": 3454536,
"Overview": "Lorem Ipsum dolor sit amet..",
"Features": "Lorem Ipsum dolor sit amet..",
"Specs": {}
}

如您所见,Specs 属性是一个空对象。我相信 JSON stringify 方法知道 Specs 属性是一个对象,因此它将 {} 附加到 stringified 周围的 JSON 字符串输出。在这种情况下是一个空字符串。然而,我希望它显示的不是一个空对象。见下文:

"Specs": {
"foo":"bar",
"baz":1,
"etc":"..."
}

我相信 JSON 库的问题区域在这里:(json2.asp)

// Otherwise, iterate through all of the keys in the object.

for (k in value) {
if (Object.hasOwnProperty.call(value, k)) {
v = str(k, value);
if (v) {
partial.push(quote(k) + (gap ? ': ' : ':') + v);
}
}
}

我假设上述代码的问题在于它假定所有对象都继承自 Object 类。 (提供 hasOwnProperty 的那个)但是我认为 COM 对象很可能不会从 Object 类继承 — 或者至少 相同 对象 类。或者至少不要实现对它们执行 for ... in 所需的任何接口(interface)。

更新:虽然我觉得回答这个问题无关紧要 — 我希望某种网络客户端请求(通过 http)该对象的 JSON 表示或该对象的集合.

tl;dr 问题:我应该怎么做才能使 Scripting.Dictionary 正确输出为 JSON,而不是失败并返回一个空的字符串?我是否需要“重新发明轮子”并在 VBScript 中编写自己的 Dictionary 类,确实充当 ASP 中的普通对象?

最佳答案

Javascript 的 for...in构造(在您引用的 JSON 序列化程序中使用)仅适用于 native JS 对象。枚举一个Scripting.Dictionary的键,你需要使用 Enumerator对象,它将枚举字典的键。

现在 JSON.stringify方法有一个允许自定义序列化的好方法,通过检查 toJSON 的存在。每个属性的方法。不幸的是,您不能像在 native JS 对象上那样在现有 COM 对象上添加新方法,所以这是行不通的。

然后是可以作为第二个参数传递给 stringify 的自定义字符串化函数方法调用。将为每个需要字符串化的对象调用该函数,即使对于每个嵌套对象也是如此。我认为可以在这里使用。

一个问题是(据我所知)JScript 无法自行区分 VBScript 类型。对于 JScript,任何 COM 或 VBScript 对象都有 typeof === 'object' .我所知道的获取该信息的唯一方法是定义一个将返回类型名称的 VBS 函数。

由于经典 ASP 文件的执行顺序如下:

  • <script>使用非默认脚本语言(在您的情况下为 JScript)的 block
  • <script>使用默认脚本语言(在您的情况下为 VBScript)的 block
  • <% ... %> block ,使用默认脚本语言(在您的情况下为 VBScript)

以下可能有效——但JSON.stringify调用在 <% ... %> 内完成括号,因为这是唯一一次同时使用 JScript 和 VBScript <script>部分都将被解析和执行。

最终的函数调用是这样的:

<%
Response.Write JSON.stringify(oProd, vbsStringifier)
%>

为了让 JScript 检查 COM 对象的类型,我们定义了一个 VBSTypeName 函数:

<script language="VBScript" runat="server">
Function VBSTypeName(Obj)
VBSTypeName = TypeName(Obj)
End Function
</script>

这里我们有作为第二个参数传递给 JSON.stringify 的 vbsStringifier 的完整实现:​​

<script language="JScript" runat="server">

function vbsStringifier(holder, key, value) {
if (VBSTypeName(value) === 'Dictionary') {
var result = '{';
for(var enr = new Enumerator(value); !enr.atEnd(); enr.moveNext()) {
key = enr.item();
result += '"' + key + '": ' + JSON.stringify(value.Item(key));
}
result += '}';
return result;
} else {
// return the value to let it be processed in the usual way
return value;
}
}

</script>

当然,在脚本引擎之间来回切换不是很有效(即从 JS 调用 VBS 函数,反之亦然),因此您可能希望尽量减少这种情况。


另请注意,我无法对此进行测试,因为我的机器上不再有 IIS。基本原理应该可行,我不是 100% 确定从 VBScript 传递 JScript 函数引用的可能性。您可能需要为 JScript 中的 JSON.stringify 调用编写一个小的自定义包装函数:

<script runat="server" language="JScript">
function JSONStringify(object) {
return JSON.stringify(object, vbsStringifier);
}
</script>

之后您可以简单地调整 VBScript 调用:

<%
Response.Write JSONStringify(oProd)
%>

关于javascript - JSON.Stringify 在 Scripting.Dictionary 对象上失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5328858/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com