2 Stimmen

c# JavaScriptConverter - Wie deserialisiere ich eine benutzerdefinierte Eigenschaft?

Ich habe eine Klasse, die in JSON serialisiert wurde, und die ich versuche, in ein Objekt zu deserialisieren.

z.B..

public class ContentItemViewModel
{
    public string CssClass { get; set; }
    public MyCustomClass PropertyB { get; set; }
}

die einfache Eigenschaft (CssClass) wird mit deserialisiert:

 var contentItemViewModels = ser.Deserialize<ContentItemViewModel>(contentItems);

Aber PropertyB bekommt einen Fehler...

Wir haben einen JavaScriptConverter hinzugefügt:

  ser.RegisterConverters(new List<JavaScriptConverter>{ publishedStatusResolver});

Als wir jedoch "MyCustomClass" als "SupportedType" hinzufügten, wurde die Methode "Deserialize" nie aufgerufen. Wenn wir jedoch ContentItemViewModel als SupportedType haben, dann wird Deserialize aufgerufen.

Wir haben eine aktuelle Lösung, die in etwa so aussieht:

class ContentItemViewModelConverter : JavaScriptConverter
{

    public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer)
    {
        var cssClass =  GetString(dictionary, "cssClass"); //I'm ommitting the GetString method in this example...           
        var propertyB= GetString(dictionary, "propertyB");

        return new ContentItemViewModel{    CssClass = cssClass , 
                                            PropertyB = new MyCustomClass(propertyB)}
    }

    public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)
    {
        throw new Exception("Only does the Deserialize");
    }

    public override IEnumerable<Type> SupportedTypes
    {
        get
        {
            return new List<Type>
                {
                    typeof(ContentItemViewModel)
                };
        }
    }
}

Aber wir würden eine einfachere Lösung von nur deserializing MyCustomClass bevorzugen, da es eine Reihe von anderen Feldern, die auf das ViewModel sind, und es scheint eine Verschwendung zu haben, diesen Konverter jedes Mal zu bearbeiten, wenn wir eine Eigenschaft ändern/hinzufügen....

Gibt es eine Möglichkeit, JUST PropertyB vom Typ MyCustomClass zu deserialisieren?

Vielen Dank für Ihre Hilfe!

0voto

parapura rajkumar Punkte 23657

Haben Sie die Verwendung von DatacontractJsonSerializer

[DataContract]
public class MyCustomClass
{
    [DataMember]
    public string foobar { get; set; }
}

[DataContract]
public class ContentItemViewModel
{
    [DataMember]
    public string CssClass { get; set; }
    [DataMember]
    public MyCustomClass PropertyB { get; set; }
}

class Program
{
    static void Main(string[] args)
    {

        ContentItemViewModel model = new ContentItemViewModel();
        model.CssClass = "StackOver";
        model.PropertyB = new MyCustomClass();
        model.PropertyB.foobar = "Flow";

        //Create a stream to serialize the object to.
        MemoryStream ms = new MemoryStream();

        // Serializer the User object to the stream.
        DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(ContentItemViewModel));
        ser.WriteObject(ms, model);
        byte[] json = ms.ToArray();
        ms.Close();
        string s=  Encoding.UTF8.GetString(json, 0, json.Length);

        Console.ReadLine();
    }
}

Fügen Sie alle möglichen Klassen zu DatacontractJsonSerializer.KnownTypes wenn MyCustomClass Ableitungen hat.

0voto

Rolf Punkte 610

Was auch immer es nach all der Zeit wert sein mag, aber ich bin über das gleiche Problem gestolpert und die Lösung ist, dass der Deserializer keine Ahnung von den Klassen hat, die Sie deserialisieren, es sei denn, Sie geben ihm die notwendigen Informationen.

Auf der obersten Ebene kennt er den Typ aus dem Parameter type von Deserialize<>(). Deshalb ist Ihr Konverter für ContentItemViewModel funktioniert. Für verschachtelte Objekte benötigt es __type-Eigenschaften und einen JavaScriptTypeResolver.

var ser = new JavaScriptSerializer(new SimpleTypeResolver());
ser.RegisterConverters(myconverters);
MyClass myObject = new MyClass();
string json = ser.Serialize(myObject);
    // set a breakpoint here to see what has happened
ser.Deserialize<MyClass>(json);

Ein TypeResolver fügt eine __type-Eigenschaft zu jedem serialisierten Objekt hinzu. Sie können einen benutzerdefinierten TypeResolver schreiben, der Kurznamen verwendet. In diesem Beispiel verwende ich den SimpleTypeResolver von .net, der "einfach" den voll qualifizierten Typnamen als __type speichert. Beim Deserialisieren findet der JavaScriptDeserializer __type und fragt den TypeResolver nach dem richtigen Typ. Dann kennt er einen Typ und kann eine registrierte Methode JavaScriptConverter.Deserialize aufrufen.

Ohne einen TypeResolver werden Objekte in ein Dictionary deserialisiert, da JavaScriptSerializer keine Typinformationen hat.

Wenn Sie keine __type-Eigenschaft in Ihrer json-Zeichenfolge angeben können, müssen Sie zunächst in ein Dictionary deserialisieren und dann einen "Vermutungsschritt" hinzufügen, der die Felder interpretiert, um den richtigen Typ zu finden. Dann können Sie die ConvertToType-Methode von JavaScriptSerializer verwenden, um das Wörterbuch in die Felder und Eigenschaften des Objekts zu kopieren.

Wenn Sie den von ASP.NET bereitgestellten JavaScriptSerializer verwenden müssen und keinen eigenen erstellen können, beachten Sie diesen Abschnitt aus der .ctor-Hilfe von JavaScriptSerializer:

Die Instanz von JavaScriptSerializer, die von der asynchronen Kommunikationsschicht für den Aufruf von Webdiensten aus einem Client-Skript verwendet wird, verwendet einen speziellen Typauflöser. Dieser Typauflöser beschränkt die Typen, die deserialisiert werden können, auf diejenigen, die in der Methodensignatur des Webdienstes definiert sind, oder auf diejenigen, auf die das GenerateScriptTypeAttribut angewendet wurde. Sie können diesen eingebauten Typauflöser nicht programmatisch ändern.

Vielleicht kann Ihnen das Attribut GenerateScriptType helfen. Aber ich weiß nicht, welche Art von __type Properties hier benötigt werden.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X