Почему JavaScriptSerializer возвращает неверный ответ при вызове из JScript.NET?

В ASP.NET/С#:

<%@ 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"]

Это кажется полностью сломанным. Это можно исправить, явно объявив тип данных Fruits, что превращает его в «собственный массив»:

<%@ 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 медленнее, чем собственные массивы, но они все равно должны работать, верно?


person Robert Calhoun    schedule 15.07.2010    source источник


Ответы (2)


Похоже на проблему вывода типа - т.е., возможно, JScript.NET интерпретировал ["apple","banana","crunchberries"] как массив целых чисел.

Вы можете попробовать создать функцию, которая принимает object и вызывает ее вместо JavaScriptSerializer.Serialize. Проверьте переданное значение, чтобы увидеть, что это такое.

person Igor Zevaka    schedule 15.07.2010
comment
Ну, да, но я думаю, что работа сериализатора заключается в проверке типов данных. Поработав над этим некоторое время, кажется, что сериализатор в порядке, но JScript отправляет ему плохо определенный объект. - person Robert Calhoun; 15.07.2010

Я обвинял 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], что правильно. Порт этого кода (в комплекте с явными объявлениями типов для скаляров и созданием экземпляров массива объектов Framework длиной 3) для JScript также дает правильный ответ:

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 только что представил «динамические» типы и объекты Expando, которые могут выполняться под новая среда выполнения "DLR", так что, по-видимому, теперь можно было бы сделать менее причудливую версию JScript.

person Robert Calhoun    schedule 15.07.2010