2015-10-02 20 views
5

JSON.NET enthält Eigenschaftenattribute wie [JsonIgnore] und [JsonProperty].Hinzufügen eines benutzerdefinierten Attributs zu json.net

Ich möchte einige benutzerdefinierte erstellen, die ausgeführt werden, wenn die Serialisierung z. [JsonIgnoreSerialize] oder [JsonIgnoreDeserialize]

Wie würde ich über die Erweiterung des Rahmens gehen, um dies zu umfassen?

+0

tun müssen, um sie Attribute sein? Was möchten Sie in Ihrem benutzerdefinierten Serialisierungsattribut tun? –

+0

Ich möchte eine Eigenschaft bei der Serialisierung, aber nicht bei der Deserialisierung ignorieren können. Ich dachte, es wäre einfach, einfach ein Attribut hinzuzufügen, z. '[JsonIgnoreSerialize]' an die Eigenschaft. –

Antwort

2

Da Ihr Ziel ist, eine Eigenschaft bei der Serialisierung, aber nicht bei der Deserialisierung zu ignorieren, können Sie eine ContractResolver verwenden.

Beachten Sie, dass die folgende Klasse genau das tut und auf CamelCasePropertyNamesContractResolver basiert, um sicherzustellen, dass sie in Kamel-JSON-Feldern serialisiert. Wenn Sie das nicht möchten, können Sie stattdessen von DefaultContractResolver erben.

Auch das Beispiel, das ich selbst hatte, basiert auf dem Namen einer Zeichenfolge, aber Sie können leicht überprüfen, ob die Eigenschaft von Ihrem benutzerdefinierten Attribut geschmückt ist, anstatt den Eigenschaftsnamen zu vergleichen.

public class CamelCaseIgnoringPropertyJsonResolver<T> : CamelCasePropertyNamesContractResolver 
{   
    protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization) 
    { 
     // list the properties to ignore 
     var propertiesToIgnore = type.GetProperties() 
       .Where(x => x.GetCustomAttributes().OfType<T>().Any()); 

     // Build the properties list 
     var properties = base.CreateProperties(type, memberSerialization); 

     // only serialize properties that are not ignored 
     properties = properties 
      .Where(p => propertiesToIgnore.All(info => info.Name != p.UnderlyingName)) 
      .ToList(); 

     return properties; 
    } 
} 

Dann können Sie es wie folgt:

static private string SerializeMyObject(object myObject) 
    { 
     var settings = new JsonSerializerSettings 
     { 
      ContractResolver = new CamelCaseIgnoringPropertyJsonResolver<JsonIgnoreSerializeAttribute>() 
     }; 

     var json = JsonConvert.SerializeObject(myObject, settings); 
     return json; 
    } 

Schließlich kann das benutzerdefinierte Attribut von jeder Art sein, aber das Beispiel zum Spiel:

internal class JsonIgnoreSerializeAttribute : Attribute 
{ 
} 

Der Ansatz ist getestet und funktioniert auch mit verschachtelten Objekten.

+0

... kümmern sich um die down vote? –

+0

Ich habe nicht downvote, aber ich würde vermuten, der Grund ist, dass Ihre Lösung nicht zeigt, wie die benutzerdefinierten Attribute zu implementieren, wie ursprünglich gefragt wurde. Stattdessen muss der Name der Eigenschaft an den Resolver übergeben werden, der ignoriert werden soll, und nur diese einzelne Eigenschaft wird behandelt. Was, wenn es mehr als eins gibt? –

+0

Fair genug, Brian. Danke für den konstruktiven Kommentar :) –

5

Sie können einen benutzerdefinierten Vertrag Resolver schreiben ähnliche

public class MyContractResolver<T> : Newtonsoft.Json.Serialization.DefaultContractResolver 
             where T : Attribute 
{ 
    Type _AttributeToIgnore = null; 

    public MyContractResolver() 
    { 
     _AttributeToIgnore = typeof(T); 
    } 

    protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization) 
    { 
     var list = type.GetProperties() 
        .Where(x => !x.GetCustomAttributes().Any(a => a.GetType() == _AttributeToIgnore)) 
        .Select(p => new JsonProperty() 
        { 
         PropertyName = p.Name, 
         PropertyType = p.PropertyType, 
         Readable = true, 
         Writable = true, 
         ValueProvider = base.CreateMemberValueProvider(p) 
        }).ToList(); 

     return list; 
    } 
} 

Sie es in Serialisierung/Deserialisierung wie

können
var json = JsonConvert.SerializeObject(
      obj, 
      new JsonSerializerSettings() { 
       ContractResolver = new MyContractResolver<JsonIgnoreSerialize>() 
      }); 

var obj = JsonConvert.DeserializeObject<SomeType>(
      json, 
      new JsonSerializerSettings() { 
       ContractResolver = new MyContractResolver<JsonIgnoreDeserialize>() 
      }); 
+2

Diese Lösung funktioniert wie angekündigt, aber es hat ein Problem: Es entspricht nicht den Standard-Json.NET-Attributen '[JsonIgnore]' und (noch wichtiger) '[JsonProperty]'. Siehe https://dotnetfiddle.net/Et265h. Sie sollten zuerst 'base.CreateProperties()' aufrufen und dann diese Liste basierend auf den benutzerdefinierten Attributen filtern. Siehe https://dotnetfiddle.net/gDGfrO. –

Verwandte Themen