2017-01-20 2 views
0
{ 
    "Class1": { 
     "Class2": [ 
      {"Name": "DerivedV1"}, 
      {"Name": "DerivedV2"}, 
      {"Name": "DerivedV3"} 
     ] 
    } 
} 

JsonConvert.DeserializeObject<Class1>(jsonString, settings); 

public class Class1 
{ 
    public List<BaseClass> DerivedClasses { get; set; } 
} 

public abstract BaseClass 
{ 
    public string Name { get; set; } 

    public abstract bool DoSomething; 
} 

public class DerivedV1 : BaseClass 
{ 
    public override bool DoSomething() 
    { 
     // Logic here, different for each derived class. 
    } 
} 

Wenn ich Class1 zu deserialisieren versuche, kann ich nicht herausfinden, wie man die Liste der abgeleiteten Klassen von Name erstellt. Ich kann nicht so etwas wie List BaseClass deklarieren, wo BaseClass abstrakt ist, und ich bin nicht sicher, wie Reflektion während der Deserialisierung in Class2 zu verwenden, um die abgeleitete Klasse aus dem "Name" -Wert zu bestimmen. Ich habe mich auch mit ICloneable beschäftigt, kam aber in diesem Zusammenhang nicht weiter.Deserialisieren von JSON in abgeleitete Klassen

Edit:

Hier ist, was ich am Ende zu schaffen und fordern von bekommen und setzen

public static List<T> DeserializeJObjectsToObjects<T>(IEnumerable<JObject> jObjects, string typeKey, string nameSpaceOfClass) 
    { 
     Assembly assembly = Assembly.GetExecutingAssembly(); 
     List<T> convert = new List<T>(); 

     foreach (var jObject in jObjects) 
     { 
      JToken typeName; 
      jObject.TryGetValue(typeKey, out typeName); 
      string fullNameSpace = string.Format(namespaceFormat, nameSpaceOfClass, typeName); 
      Type t = Type.GetType(string.Format(fullNameSpace)); 
      convert.Add((T) Activator.CreateInstance(t)); 
     } 

     return convert; 
    } 

    public static List<JObject> SerializeObjectsToJObjects<T>(IEnumerable<T> variableObjects) 
    { 
     List<JObject> convert = new List<JObject>(); 

     foreach (T variableObject in variableObjects) 
     { 
      var jsonString = JsonConvert.SerializeObject(variableObject); 
      convert.Add(JObject.Parse(jsonString)); 
     } 

     return convert; 
    } 
+0

Können Sie Code bereitstellen, den Sie während der Deserialisierung versucht haben? – ragerory

+0

Was versuchen Sie zu erreichen, was ist das erwartete Ergebnis der Deserialisierung des von Ihnen bereitgestellten JSON? – ironstone13

+0

Ich habe einen Basiscode hinzugefügt, den ich ausprobiert habe, der nicht funktioniert, aber hoffentlich zeigt, was ich versuche zu tun. – user2680142

Antwort

0

Zuerst einige Hinweise - ich verwende JSonConvert nicht, aber es gibt Artikel, die Ihnen zeigen, wie um dies zu tun. Siehe zum Beispiel Json.net serialize/deserialize derived types?. Sie haben jedoch kein json.net-Tag hinzugefügt, also nehme ich an, dass dies hoffentlich helfen oder zumindest auf den richtigen Ort hinweisen soll.

Ich habe den eingebauten .Net JavaScriptSerializer verwendet. Möglicherweise müssen Sie dies anpassen, um mit Ihrer Eingabe zu arbeiten. Ich habe meine Eingabe basierend auf Ihrem Code erstellt, und mein Json sieht nicht so aus wie Ihres. Du hast vielleicht noch etwas Arbeit übrig. Ich konnte es mit einem SimpleTypeResolver arbeiten lassen. Code unten:

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Drawing; 
using System.IO; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 
using System.Web.Script.Serialization; 
using System.Windows.Forms; 
using System.Xml.Serialization; 

namespace WindowsFormsApplication6 
{ 
public partial class Form1 : Form 
{ 
    public Form1() 
    { 
     InitializeComponent(); 
    } 

    private void button1_Click(object sender, EventArgs e) 
    { 
     Class1 oClass = new Class1(); 
     DerivedV1 v1 = new DerivedV1(); 
     v1.Name = "DerivedV1"; 
     oClass.DerivedClasses.Add(v1); 
     DerivedV2 v2 = new DerivedV2(); 
     v2.Name = "DerivedV2"; 
     oClass.DerivedClasses.Add(v2); 
     DerivedV3 v3 = new DerivedV3(); 
     v3.Name = "DerivedV3"; 
     oClass.DerivedClasses.Add(v3); 
     JavaScriptSerializer ser = new JavaScriptSerializer(new SimpleTypeResolver()); 
     string sSer = ser.Serialize(oClass); 

     var test =ser.Deserialize(sSer,typeof(Class1)); 
     foreach (var tst in ((Class1)test).DerivedClasses) 
     { 
      Console.WriteLine(tst.Name + Environment.NewLine); 
      Console.WriteLine(tst.GetType().ToString() + Environment.NewLine); 
     } 
    } 
    public class Class1 
    { 
     public List<BaseClass> DerivedClasses { get; set; } 
     public Class1() 
     { 
      DerivedClasses = new List<BaseClass>(); 
     } 
    } 
    public abstract class BaseClass 
    { 
     public string Name { get; set; } 
     private bool _dosom; 

     public abstract bool DoSomething(); 
     public BaseClass(){} 
    }  
    public class DerivedV1 : BaseClass 
    { 
     public override bool DoSomething() 
     { 
      return true; 
      // Logic here, different for each derived class. 
     } 
    } 
    public class DerivedV2 : BaseClass 
    { 
     public override bool DoSomething() 
     { 
      return false; 
      // Logic here, different for each derived class. 
     } 
    } 
    public class DerivedV3 : BaseClass 
    { 
     public override bool DoSomething() 
     { 
      return true; 
      // Logic here, different for each derived class. 
     } 
    } 
} 
} 

meine Ausgabe json (mit SimpleTypeResolver):

{"__type":"WindowsFormsApplication6.Form1+Class1, WindowsFormsApplication6, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null","DerivedClasses":[{"__type":"WindowsFormsApplication6.Form1+DerivedV1, WindowsFormsApplication6, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null","Name":"DerivedV1"},{"__type":"WindowsFormsApplication6.Form1+DerivedV2, WindowsFormsApplication6, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null","Name":"DerivedV2"},{"__type":"WindowsFormsApplication6.Form1+DerivedV3, WindowsFormsApplication6, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null","Name":"DerivedV3"}]} 

und ohne den Typ Resolver, zum Vergleich (verursacht Fehler):

{"DerivedClasses":[{"Name":"DerivedV1"},{"Name":"DerivedV2"},{"Name":"DerivedV3"}]} 

Und wenn ich deserialisieren (in der for-Schleife, Console.WriteLine) ...

DerivedV1 

WindowsFormsApplication6.Form1+DerivedV1 

DerivedV2 

WindowsFormsApplication6.Form1+DerivedV2 

DerivedV3 

WindowsFormsApplication6.Form1+DerivedV3 
+0

Dies würde nicht funktionieren, wenn Sie direkt aus dem Text deserialisieren, wie ein Benutzer eingeben würde. Wenn Sie JavaScriptSerializer für das Objekt verwenden, erhalten Sie zusätzliche Informationen hinzugefügt wie "__type": "WindowsFormsApplication6.Form1 + DerivedV2. Sie sind in bestimmten Fällen richtig, aber nicht genau das, was ich suche. Ich möchte JSON Template-Erstellung so einfach machen auf meinem Benutzer wie möglich – user2680142

+0

Ja, es muss auf diese Weise serialisiert werden.Er müsste Zugriff auf die JSON-Erstellung-Software haben, wenn nicht anders.Ich glaube, wenn er die JSON nicht generieren kann, müsste er 1 verwenden Klassenart, und verwenden Sie Logik basierend auf dem Namen (oder einem anderen Attribut) zu "DoSomething." Aber um abgeleitete Typen in eine Liste von Basistypen zu bekommen, ohne etwas zu sagen, welche abgeleitete Art? Ich bin mir ziemlich sicher, dass Sie müssten Code, dass Sie selbst. Können Sie sich einen Weg vorstellen, um es mit vorhandenen Serialisierern zu tun? – Aaron

+0

Es gibt nicht, glaube ich nicht.Ich habe keine Möglichkeit gesehen, einen Wert anzugeben, um Klasse Typ von abzuleiten habe das gerade "funktioniert", ist das in BaseClass für die richtigen DervicedClasses ty Ich habe den Getter und Setter nur eine private Liste von JObjects bearbeiten von JSON erstellt. Der Getter verwendet Activator, um die richtige Instanz zu erstellen, der Setter nummeriert einfach jedes Element und legt die Liste fest. – user2680142

0

Verwenden Sie dies als meine Lösung.

public static List<T> DeserializeJObjectsToObjects<T>(IEnumerable<JObject> jObjects, string typeKey, string nameSpaceOfClass) 
    { 
     Assembly assembly = Assembly.GetExecutingAssembly(); 
     List<T> convert = new List<T>(); 

     foreach (var jObject in jObjects) 
     { 
      JToken typeName; 
      jObject.TryGetValue(typeKey, out typeName); 
      string fullNameSpace = string.Format(nameSpaceFormat, nameSpaceOfClass, typeName); 
      Type t = Type.GetType(string.Format(fullNameSpace)); 
      convert.Add((T) Activator.CreateInstance(t)); 
     } 

     return convert; 
    } 

    public static List<JObject> SerializeObjectsToJObjects<T>(IEnumerable<T> variableObjects) 
    { 
     List<JObject> convert = new List<JObject>(); 

     foreach (T variableObject in variableObjects) 
     { 
      var jsonString = JsonConvert.SerializeObject(variableObject); 
      convert.Add(JObject.Parse(jsonString)); 
     } 

     return convert; 
    }