views:

36

answers:

2

In 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>

returns fruits=["apple","banana","crunchberries"]

In 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>

returns fruits=["apple","banana","crunchberries"]

But in 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>

returns fruits=["0","1","2"]

This seems completely broken. It can be fixed by explicitly declaring the data type of fruits, which makes this into a "native array":

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

returns fruits=["apple","banana","crunchberries"]

I don't see why the type is mandatory to get the correct serialization. (var fruits = ["apple","banana","crunchberries",5] might be bad code but it's legal in both Javascript and Jscript.) JScript arrays are suppose to be slower than native arrays, but they're still suppose to work, right?

+1  A: 

Looks like a type inference issue - i.e. perhaps JScript.NET interpreted ["apple","banana","crunchberries"] as array of ints.

You can try creating a function that takes an object and cal that instead of JavaScriptSerializer.Serialize. Inspect the value being passed in to see what it is.

Igor Zevaka
Well, yeah, but I sort of think it is the serializer's job to handle inspecting data types. After pounding on this a while it looks like the serializer is ok, but JScript is sending it a poorly-defined object.
Robert Calhoun
A: 

I've been blaming JavaScriptSerializer, but the issue seems to be related to the split-personality disorder that JScript has with "JScript" data types vs ".NET Framework" datatypes.

First, exoneration of JavaScriptSerializer. It can handle mixed data types in an array, as shown in this VB example:

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)

This returns ["apple",5,22.22222], which is correct. A port of this code (complete with explicit type declarations for scalars and instantiation of a length 3 array of Framework objects) to JScript also gives the correct answer:

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);

But nobody writes Javascript that way. Instead you'd write a flexible-type stack using:

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

which uses JScript "expando" array objects. That's just fine as long as you stay in the JScript context, but calling anything in the framework is asking for trouble.

The core issue here is failure of JScript to convert JScript objects into Framework (CLR) arrays and objects as necessary. There is sort of warning about this in the JScript 10.0 Array Object discussion. ("Consequently, when type-annotating the parameters and return types of CLS-compliant methods, make sure to use the System.Array data type instead of the Array object.") Wow, I'm sure glad the JScript compiler is looking out for me!

It's hard to say anything good about JScript.NET here. It seems like asking for trouble to have an environment with two subtly different kinds of arrays and two subtly different kinds of objects. Oddly, Visual C# 2010 just introduced "dynamic" types and Expando objects that can execute under the new "DLR" runtime, so presumably one could now make a less quirky version of JScript.

Robert Calhoun