I'm trying to write a custom JavascriptConverter for use with a WebService I'm writing. I have to write a custom converter, because Microsoft.JScript.JSObject doesn't support IDictionary, so it gets treated as an array. I have this part working fine. However, because Microsoft.JScript.ArrayObject is a subclass of Microsoft.JScript.JSObject, it also trys to convert it using the same method. How can I return something that will be serialized as a JSON array? I have to return an IDictionary, which will become a JSON object. Is there something I'm missing?
Specifically, how do I return something from Serialize that gets serialized as an Array, not as an Object.
Thanks!
EDIT:
I guess I need to be more specific.
Microsoft.JScript.JSObject implements IEnumerable, but not IDictionary. Microsoft.JScript.ArrayObject is a subclass of Microsoft.JScript.JSObject. If I create a .asmx in JScript.NET, when I try to return a JSObject, it gets serialized as an array (because it implements IEnumerable, but not IDictionary), which means that only the property names in the object get serialized. Of course, If I hand back an ArrayObject, it works properly, and serializes it as an array.
So, I implemented a subclass of JavascriptConverter, which says that its SupportedType is Microsoft.JScript.JSObject. Now, JSObjects get properly serialized. However, because ArrayObject is a subclass of JSObject, JavascriptSerializer no longer takes care of serializing ArrayObjects itself, it hands it off to the JSObject serializer. The question is, how does my custom serializer return something that the JavaScriptSerializer will properly treat as an array, not as an object -- Serialize is forced to return an IDictionary, and that gets serialized as an object, not an array.
Does this question make more sense?
BTW: I've looked at WCF and C# instead, but the DataContractJsonSerializer output is completely useless unless you're going to only ever access it using a WCF client; I'm planning to retrieve it using jQuery.
Answer:
I finally understood what bdukes was trying to say, and it works! You need to tell it it's an array when returning the dictionary (although this won't work for a top-level array). Here is the Serialize
function that I would up writing:
public override IDictionary<string, object> Serialize (object obj, JavaScriptSerializer serializer) {
JSObject jsobj = obj as JSObject;
Dictionary<string, object> netdict = new Dictionary<string, object>();
if (jsobj != null) {
foreach (string prop in jsobj) {
object value = jsobj.GetField(prop, BindingFlags.Default).GetValue(jsobj);
switch (value.GetType().FullName) {
case "Microsoft.JScript.ArrayObject":
object[] arr_obj = ((IEnumerable)(Microsoft.JScript.ArrayObject)value).Cast<object>().ToArray<object>();
netdict.Add(prop, arr_obj);
break;
default:
netdict.Add(prop, value);
break;
}
}
}
return netdict;
}