2013-08-31 16 views
34

Json.NETシリアライザを使用し、JsonIgnore属性を使用しないで取得専用プロパティを無視する方法はありますか?JsonIgnore属性を使用せずにJson.NETでget-onlyプロパティを無視する方法はありますか?

は例えば、私はこれらを持つクラスを持って取得するプロパティ:

public Keys Hotkey { get; set; } 

    public Keys KeyCode 
    { 
     get 
     { 
      return Hotkey & Keys.KeyCode; 
     } 
    } 

    public Keys ModifiersKeys 
    { 
     get 
     { 
      return Hotkey & Keys.Modifiers; 
     } 
    } 

    public bool Control 
    { 
     get 
     { 
      return (Hotkey & Keys.Control) == Keys.Control; 
     } 
    } 

    public bool Shift 
    { 
     get 
     { 
      return (Hotkey & Keys.Shift) == Keys.Shift; 
     } 
    } 

    public bool Alt 
    { 
     get 
     { 
      return (Hotkey & Keys.Alt) == Keys.Alt; 
     } 
    } 

    public Modifiers ModifiersEnum 
    { 
     get 
     { 
      Modifiers modifiers = Modifiers.None; 

      if (Alt) modifiers |= Modifiers.Alt; 
      if (Control) modifiers |= Modifiers.Control; 
      if (Shift) modifiers |= Modifiers.Shift; 

      return modifiers; 
     } 
    } 

    public bool IsOnlyModifiers 
    { 
     get 
     { 
      return KeyCode == Keys.ControlKey || KeyCode == Keys.ShiftKey || KeyCode == Keys.Menu; 
     } 
    } 

    public bool IsValidKey 
    { 
     get 
     { 
      return KeyCode != Keys.None && !IsOnlyModifiers; 
     } 
    } 

私は(私も他の多くのクラスを持っている)それらのすべてに[JsonIgnore]を追加する必要がある、またはすべて無視する良い方法はありますか取得専用プロパティ?

答えて

53

カスタムIContractResolverを実装し、直列化の際にこれを使用することによってこれを行うことができます。あなたがDefaultContractResolverをサブクラス化する場合は、これを行うことは非常に容易になる:ここで

class WritablePropertiesOnlyResolver : DefaultContractResolver 
{ 
    protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization) 
    { 
     IList<JsonProperty> props = base.CreateProperties(type, memberSerialization); 
     return props.Where(p => p.Writable).ToList(); 
    } 
} 

はそれを使用する方法を示すテストプログラムです:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using Newtonsoft.Json; 
using Newtonsoft.Json.Serialization; 

class Program 
{ 
    static void Main(string[] args) 
    { 
     Widget w = new Widget { Id = 2, Name = "Joe Schmoe" }; 

     JsonSerializerSettings settings = new JsonSerializerSettings 
     { 
      ContractResolver = new WritablePropertiesOnlyResolver() 
     }; 

     string json = JsonConvert.SerializeObject(w, settings); 

     Console.WriteLine(json); 
    } 
} 

class Widget 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 
    public string LowerCaseName 
    { 
     get { return (Name != null ? Name.ToLower() : null); } 
    } 
} 

ここでは上記の出力があります。読み取り専用プロパティLowerCaseNameは出力に含まれていないことに注意してください。

{"Id":2,"Name":"Joe Schmoe"} 
+0

どのようにSETなしのプロパティのみを無視しますか?そしてパブリック文字列のようにプライベートセットを持つときにはまだシリアル化します。Name {get;プライベートセット; }? –

12

JSON.netのOptInモードを使用すると、シリアル化するプロパティを装飾するだけで済みます。これは、自動的にすべての読み取り専用プロパティをオプトアウトするほど良くはありませんが、作業を節約できます。

[JsonObject(MemberSerialization.OptIn)] 
public class MyClass 
{ 
    [JsonProperty] 
    public string serializedProp { get; set; } 

    public string nonSerializedProp { get; set; } 
} 

UDATE:上記の解決策はまだかなりあなたが探しているされていない場合はどうすれば、あなたはその後、シリアライズされるだろう辞書オブジェクトを作成するためにリフレクションを使用することができ反射

を使用して別の可能性を追加しました。もちろん、以下の例は単純なクラスに対してのみ機能するため、クラスに他のクラスが含まれている場合は再帰を追加する必要があります。これは、少なくとも正しい方向にあなたを指す必要があります。

辞書にフィルタリングされた結果を置くためのサブルーチン:

private Dictionary<String, object> ConvertToDictionary(object classToSerialize) 
    { 
     Dictionary<String, object> resultDictionary = new Dictionary<string, object>(); 

     foreach (var propertyInfo in classToSerialize.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance)) 
     { 
      if (propertyInfo.CanWrite) resultDictionary.Add(propertyInfo.Name, propertyInfo.GetValue(classToSerialize, null)); 
     } 

     return resultDictionary; 
    } 

その使用を示す抜粋:

SampleClass sampleClass = new SampleClass(); 
sampleClass.Hotkey = Keys.A; 
var toSerialize = ConvertToDictionary(sampleClass); 
String resultText = JsonConvert.SerializeObject(toSerialize); 
7

あなたはこのように契約リゾルバを使用することができます。

public class ExcludeCalculatedResolver : DefaultContractResolver 
{ 
    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) 
    { 
     var property = base.CreateProperty(member, memberSerialization); 
     property.ShouldSerialize = _ => ShouldSerialize(member); 
     return property; 
    } 

    internal static bool ShouldSerialize(MemberInfo memberInfo) 
    { 
     var propertyInfo = memberInfo as PropertyInfo; 
     if (propertyInfo == null) 
     { 
      return false; 
     } 

     if (propertyInfo.SetMethod != null) 
     { 
      return true; 
     } 

     var getMethod = propertyInfo.GetMethod; 
     return Attribute.GetCustomAttribute(getMethod, typeof(CompilerGeneratedAttribute)) != null; 
    } 
} 

それは計算のプロパティを除外しますが、唯一のプロパティとsetメソッドを持つすべてのプロパティを取得するC#6が含まれます。

4

Json.netには、属性または契約リゾルバなしでプロパティを条件付きでシリアル化する機能があります。プロジェクトをJson.netに依存させたくない場合に特に便利です。 Json.net documentation

1として

条件付きで、プロパティをシリアル化するプロパティとして と同じ名前をブール値を返すメソッドを追加し、 ShouldSerializeとメソッド名の接頭辞。このメソッドの結果は、 プロパティがシリアル化されているかどうかを判断します。メソッドがtrueを返した場合は、プロパティー がシリアル化され、falseを戻す場合は、プロパティーはスキップされます( )。

関連する問題