2009-02-27 2 views
2

Ich versuche, einen benutzerdefinierten JavascriptConverter für die Verwendung mit einem WebService schreiben, die ich schreibe. Ich muss einen benutzerdefinierten Konverter schreiben, weil Microsoft.JScript.JSObject IDictionary nicht unterstützt, also wird es wie ein Array behandelt. Ich habe diesen Teil gut funktioniert. Da Microsoft.JScript.ArrayObject jedoch eine Unterklasse von Microsoft.JScript.JSObject ist, versucht es auch, es mit derselben Methode zu konvertieren. Wie kann ich etwas zurückgeben, das als JSON-Array serialisiert wird? Ich muss ein IDictionary zurückgeben, das ein JSON-Objekt wird. Gibt es etwas, das mir fehlt?Wie wird beim Erstellen eines JavascriptConverters ein Array zurückgegeben?

Wie kann ich etwas von Serialize zurückgeben, das als Array serialisiert wird, nicht als Objekt?

Danke!

EDIT:

Ich glaube, ich brauche mehr spezifisch.

Microsoft.JScript.JSObject implementiert IEnumerable, aber nicht IDictionary. Microsoft.JScript.ArrayObject ist eine Unterklasse von Microsoft.JScript.JSObject. Wenn ich in JScript.NET eine .asmx-Datei erstelle, wenn ich versuche, ein JSObject zurückzugeben, wird es als Array serialisiert (weil es IEnumerable, aber nicht IDictionary implementiert), was bedeutet, dass nur die Eigenschaftsnamen im Objekt serialisiert werden. Natürlich, wenn ich ein ArrayObject zurück gebe, funktioniert es richtig und serialisiert es als ein Array.

Also habe ich eine Unterklasse von JavascriptConverter implementiert, die besagt, dass es sich bei SupportedType um Microsoft.JScript.JSObject handelt. Jetzt werden JSObjects ordnungsgemäß serialisiert. Da ArrayObject jedoch eine Unterklasse von JSObject ist, kümmert sich JavaScriptSerializer nicht mehr um die Serialisierung von ArrayObjects selbst, sondern übergibt sie an den JSObject-Serializer. Die Frage ist, wie gibt mein benutzerdefinierter Serializer etwas zurück, das der JavaScriptSerializer korrekt als Array behandelt, nicht als Objekt - Serialize muss ein IDictionary zurückgeben und wird als Objekt und nicht als Array serialisiert.

Macht diese Frage mehr Sinn?

BTW: Ich habe WCF und C# stattdessen angeschaut, aber die DataContractJsonSerializer-Ausgabe ist völlig nutzlos, es sei denn, Sie werden immer nur mit einem WCF-Client darauf zugreifen; Ich plane, es mit jQuery abzurufen.

Antwort:

ich endlich verstanden, was bdukes versucht, zu sagen, und es funktioniert! Sie müssen sagen, dass es ein Array ist, wenn Sie das Wörterbuch zurückgeben (obwohl dies nicht für ein Top-Level-Array funktioniert). Hier ist die Serialize Funktion, die ich würde auf Schreiben:

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; 
    } 
+0

Was d:

public class ExampleConverter : JavaScriptConverter { /// <summary> /// Gets a collection of the supported types /// </summary> /// <value>An object that implements <see cref="IEnumerable{T}"/> that represents the types supported by the converter. </value> public override IEnumerable<Type> SupportedTypes { get { return new ReadOnlyCollection<Type>(new Type[] { typeof(MyExampleType) }); } } /// <summary> /// Converts the provided dictionary into an object of the specified type. /// </summary> /// <param name="dictionary">An <see cref="IDictionary{TKey,TValue}"/> instance of property data stored as name/value pairs. </param> /// <param name="type">The type of the resulting object.</param> /// <param name="serializer">The <see cref="JavaScriptSerializer"/> instance. </param> /// <returns>The deserialized object. </returns> /// <exception cref="InvalidOperationException">We only serialize</exception> public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer) { throw new InvalidOperationException("We only serialize"); } /// <summary> /// Builds a dictionary of name/value pairs /// </summary> /// <param name="obj">The object to serialize. </param> /// <param name="serializer">The object that is responsible for the serialization. </param> /// <returns>An object that contains key/value pairs that represent the object’s data. </returns> /// <exception cref="InvalidOperationException"><paramref name="obj"/> must be of the <see cref="MyExampleType"/> type</exception> public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer) { MyExampleType example = obj as MyExampleType; if (example == null) { throw new InvalidOperationException("object must be of the MyExampleType type"); } IDictionary<string, object> jsonExample = new Dictionary<string, object>(); jsonExample.Add("arrayMember", example.People.ToArray()); jsonExample.Add("otherMember", example.Member); return jsonExample; } } 

diese wie folgt aufgerufen wird o Sie planen, mit einem Array zu tun, das Sie mit einem Objekt nicht tun können? –

+0

Danke für die Klarstellung, obwohl ich denke, dass meine Antwort immer noch steht. Sie können das nicht tun, Sie müssen es zuerst in ein reguläres .NET-Array konvertieren. – bdukes

Antwort

9

JavaScriptConverters nur JSON-Objekte erstellen können, nicht andere Arten. Wenn Sie nur ein Array zurückgeben möchten, müssen Sie das Objekt in ein .NET-Array konvertieren und dann an die Methode Serialize senden.

Zum Beispiel ein Array von Person-Objekte zurück, etwas zu tun, wie folgt aus:

IList<Person> people = ...; 
var serializer = new JavaScriptSerializer(); 
serializer.Serialize(people.ToArray()); 

Alternativ, wenn Sie ein JSON-Objekt sind die Erstellung und wollen eine seiner Eigenschaften ein Array zu sein, sollten Sie verwenden Sie eine benutzerdefinierte Javascript, etwa so:

JavaScriptSerializer serializer = new JavaScriptSerializer(); 
serializer.RegisterConverters(new JavaScriptConverter[] { new ExampleConverter() }); 
return serializer.Serialize(myExample);