2015-10-02 7 views
5

JSON.NETには、[JsonIgnore][JsonProperty]のようなプロパティ属性が付属しています。json.netにカスタム属性を追加

シリアル化が実行されたときに実行されるカスタムカスタムアイテムを作成したいとします。 [JsonIgnoreSerialize]または[JsonIgnoreDeserialize]

これを含めるようにフレームワークを拡張するにはどうすればよいですか?

+0

のようにシリアライズ/デシリアライゼーションの中でそれを使用することができ、それらは属性である必要がありますか?あなたはカスタム直列化属性で何をしたいですか? –

+0

シリアライゼーションではプロパティを無視できますが、デシリアライゼーションでは無視できません。私は単に属性を追加するのは簡単だと思った。 '[JsonIgnoreSerialize]'をプロパティに追加します。 –

答えて

2

目的はシリアル化ではなく非シリアル化でプロパティを無視することですので、ContractResolverを使用できます。

次のクラスはキャンプケースのJsonフィールドにシリアル化されていることを確認するために、CamelCasePropertyNamesContractResolverに基づいています。あなたがそれを望まないなら、代わりにDefaultContractResolverから継承させることができます。

また、自分自身は文字列の名前に基づいていますが、プロパティ名を比較する代わりに、カスタム属性で修飾されているかどうかを簡単に確認できます。次のように

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

その後、あなたはそれを使用することができます。

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

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

最後に、カスタム属性は、任意のタイプのものとすることができるが、例を一致させるために:

internal class JsonIgnoreSerializeAttribute : Attribute 
{ 
} 

アプローチがありますテストされ、ネストされたオブジェクトでも動作します。あなたは

このような
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; 
    } 
} 

カスタム契約リゾルバを書くことができます

+0

...賛成投票を説明する気に? –

+0

私はdownvoteをしませんでしたが、その理由は、あなたの解決策が実際に尋ねられたようにカスタム属性を実装する方法を実際に示していないからです。代わりに、リゾルバに無視するプロパティの名前を渡さなければならず、その単一のプロパティだけを処理します。複数の場合はどうなりますか? –

+0

フェア、ブライアン。建設的なコメントをありがとう:) –

5

あなたは

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

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

このソリューションは広告として機能しますが、標準のJson.NET属性 '[JsonIgnore]'と(もっと重要なのは) '[JsonProperty]'を尊重しないという問題があります。 https://dotnetfiddle.net/Et265hを参照してください。最初に 'base.CreateProperties()'を呼び出してから、カスタム属性に基づいてそのリストをフィルタリングする必要があります。 https://dotnetfiddle.net/gDGfrOを参照してください。 –

関連する問題