2013-04-10 11 views
9

Ich bin mir nicht sicher, warum jemand noch nicht zu dieser Frage gefragt hat, aber ich versuche, nur einfache Arten eines bestimmten Objekts mit IContractResolver Schnittstelle zu serialisieren. Ich möchte nicht wirklich jede Eigenschaft mit ShouldSerialize Methode oder JsonDataAttribute oder etwas Ähnliches markieren.Serialize nur einfache Typen mit Json.Net

Was habe ich wie folgt auf LinqPad bisher getan gezeigt

Einige Beispiel Klassen serialisiert

class Customer 
{ 
    public List<Order> Orders {get;set;} 
    public int CustomerId {get;set;} 
    public string[] Addresses {get;set;} 
} 

class Order 
{ 
    public int OrderId{get;set;} 
    public string Name {get;set;} 
    public int Amount {get;set;} 
    public Order PreviousOrder {get;set;} 
} 

Eine Erweiterung Methode alle Objekte

static class ExtensionMethods 
{ 
    public static string JsonSerialize (this object obj) 
    { 
     var settings = new JsonSerializerSettings(); 
     settings.ContractResolver = new MyContractResolver(); 
     settings.DefaultValueHandling = DefaultValueHandling.Ignore; 
     settings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; 
     return JsonConvert.SerializeObject(obj,settings); 
    } 
} 

serialisiert Meine benutzerdefinierte Vertragsauflösung Klasse

public class MyContractResolver: DefaultContractResolver 
{ 
    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) 
    { 
     var property = base.CreateProperty(member,memberSerialization); 
     property.ShouldSerialize = instance => instance.GetType().IsPrimitive || instance.GetType() == typeof(string) || instance.GetType() == typeof(decimal); 
     return property; 
    } 
} 

und Main-Methode:

void Main() 
{ 
    var customer = new Customer 
       { 
        Orders = ProduceSomeOrders(), 
        Addresses = new string[] {"9450 S. Small Street Dr.","9521 Flintstone Dr. S"}, 
        CustomerId = 1 
       }; 

    var jsonOrder = customer.JsonSerialize(); 
    jsonOrder.Dump(); 
} 

Ich möchte nur Probentypen wie int, double, string, decimal, bool usw. aber nicht Arrays, Sammlungen, benutzerdefinierte Objekte usw. serialisiert und es wird nur die erste Ebene, nicht die zweite oder mehrere Ebenen nach unten navigieren. Ich frage mich wirklich, warum es keine einfache Methode gibt, die das in Json.Net tut.

Dies ist der Ausgang, wenn ich diesen Code ausführen: (ein leeres json)

{}

ich eine Sache realisiert habe, wenn ich diesen Code ausführen, der erste member Parameter übergeben in die CreateProperty Methode ist das Hauptobjekt selbst, das in diesem Fall Customer Instanz ist. Aber da dies für alle Arten von Typen funktioniert, möchte ich einfach nicht instance.GetType() == typeof(Customer) oder etwas ähnliches in der Methode sagen. Die erwartete Ausgabe ist in diesem Fall nur CustomerId.

Kennen Sie irgendeine anmutige Art, mit meinem Problem umzugehen?

+0

Was ist das erwartete Ergebnis der Serialisierung? Basierend auf was ich gelesen habe sollte es nur CustomerID enthalten, ist das korrekt? – Patrick

+0

@Patrick: Du hast Recht! – Tarik

+0

In der JsonSerialize-Methode ist es möglich, die Eigenschaften der "Top-Instanz" zu iterieren, um seine untergeordneten Eigenschaften zu serialisieren, und sie dann irgendwie zu einer gültigen JSON-Zeichenfolge zu mischen? – Patrick

Antwort

5

Durch Ändern der folgenden Methode habe ich das Ergebnis erhalten: {"CustomerId": 1}. Ist das wonach Sie gesucht haben?

public class MyContractResolver:DefaultContractResolver 
{ 
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) 
{ 
    var property = base.CreateProperty(member,memberSerialization); 

    var propertyType = property.PropertyType; 
    if(propertyType == typeof(int) 
     || propertyType == typeof(string)){ 
     property.ShouldSerialize = instance => true; 
    } 
    else 
    { 
     property.ShouldSerialize = instance => false; 
    } 
    return property; 
} 
} 
2

Statt des überwiegenden CreateProperty Methode, ich zwingende GetSerializableObjects Methode, da es alle möglichen Mitglieder gibt, gebe ich bekommen:

public class MyContractResolver: DefaultContractResolver 
{ 
    protected override List<MemberInfo> GetSerializableMembers(Type objectType) 
    { 
     var members = base.GetSerializableMembers(objectType); 
     var filteredMembers = new List<MemberInfo>(); 
     members.ForEach(m=>{ 
      if(m.MemberType == MemberTypes.Property) 
      { 
       PropertyInfo info = (PropertyInfo) m; 
       var type = info.PropertyType; 
       if(type.IsPrimitive || type == typeof(string) || type == typeof(decimal)) 
       { 
        filteredMembers.Add(m); 
       } 
      } 
     }); 
     return filteredMembers; 
    } 
} 
Verwandte Themen