为什么JavaScriptSerializer在从JScript.NET调用时会返回错误的答案?

时间:2010-07-15 03:46:31

标签: asp.net jscript.net javascriptserializer

在ASP.NET / C#:

<%@ Page Language="C#" %>
<%@ Import Namespace="System.Web.Script.Serialization" %>
<%
JavaScriptSerializer jss = new JavaScriptSerializer();
string[] fruits = new string[3] {"apple","banana","crunchberries"};
string output = jss.Serialize(fruits);
%>
<html>
fruits=<%=output%>
</html>

返回fruits=["apple","banana","crunchberries"]

在ASP.NET / VB.NET中:

<%@ Page Language="VB" %>
<%@ Import Namespace="System.Web.Script.Serialization" %>
<%
dim jss as new JavaScriptSerializer()
dim fruits  = new String(2) {"apple","banana","crunchberries"}
dim output as string =  jss.Serialize(fruits)
 %>
<html>
fruits=<%=output%>
</html>

返回fruits=["apple","banana","crunchberries"]

但是在ASP.NET / JScript.NET中:

<%@ Page Language="JScript" %>
<%@ Import Namespace="System.Web.Script.Serialization" %>
<%
var jss:JavaScriptSerializer = new JavaScriptSerializer;
var fruits = ["apple","banana","crunchberries"];
var output = jss.Serialize(fruits);
%>
<html>
fruits=<%=output%>
</html>

返回fruits=["0","1","2"]

这似乎彻底打破了。它可以通过明确声明水果的数据类型来修复, 这使得它变成了“原生数组”:

<%@ Page Language="JScript" %>
<%@ Import Namespace="System.Web.Script.Serialization" %>
<%
var jss:JavaScriptSerializer = new JavaScriptSerializer;
var fruits:String = ["apple","banana","crunchberries"];
var output = jss.Serialize(fruits);
%>
<html>
fruits=<%=output%>
</html>

返回fruits=["apple","banana","crunchberries"]

我不明白为什么类型必须获得正确的序列化。 (var fruits = ["apple","banana","crunchberries",5]可能是错误的代码,但它在Javascript和Jscript中都是合法的。)JScript数组假设比本机数组慢,但它们仍然可以工作,对吗?

2 个答案:

答案 0 :(得分:1)

看起来像是类型推断问题 - 也许JScript.NET将["apple","banana","crunchberries"]解释为整数数组。

您可以尝试创建一个object和cal而不是JavaScriptSerializer.Serialize的函数。检查传入的值以查看它是什么。

答案 1 :(得分:0)

我一直在指责JavaScriptSerializer,但问题似乎与JScript对“JScript”数据类型与“.NET Framework”数据类型的分裂型人格障碍有关。

首先,免除JavaScriptSerializer。它可以处理数组中的混合数据类型,如此VB示例所示:

dim a as string = "apple"
dim b as int32 = 5
dim c as double = 22.22222
dim fruits(2) as  Object
fruits(0) = a
fruits(1) = b
fruits(2) = c
dim output as string =  jss.Serialize(fruits)

这会返回["apple",5,22.22222],这是正确的。此代码的一个端口(包含显式类型声明  对JScript进行长度为3的Framework对象数组的标量和实例化也给出了正确的答案:

var a:String="apple";
var b:Int32=5;
var c:Double=22.2;
var fruits:Object = new Object[3];
fruits[0]=a;
fruits[1]=b;
fruits[2]=c;
var output = jss.Serialize(fruits);

但没有人以这种方式写Javascript。相反,您可以使用以下方法编写灵活类型的堆栈:

var fruits = new Array();
fruits.push("apple");
fruits.push(5);
fruits.push(22.22222);

使用JScript“expando”数组对象。只要你留在JScript上下文中就可以了,但是在框架中调用任何东西都会遇到麻烦。

这里的核心问题是JScript无法根据需要将JScript对象转换为Framework(CLR)数组和对象。在JScript 10.0 Array Object讨论中有关于此的警告。 (“因此,在对参数进行类型注释时 返回类型的CLS兼容方法,确保使用System.Array数据类型而不是Array对象。“)哇,我很高兴JScript编译器正在寻找我!

这里很难说JScript.NET有什么好处。似乎要求有一个环境有两个微妙不同类型的数组和两个微妙不同类型的对象。奇怪的是,Visual C#2010刚刚引入了可以在the new "DLR" runtime下执行的“动态”类型和Expando对象,因此可能现在可以制作一个不那么古怪的JScript版本。