2016-02-10 37 views
1

當採用序列Newtonsoft的JSON(8.0.0版本)DependencyObject衍生類的.Net/C#我注意到,它總是序列化DependencyObjectTypeDispatcher對象與我所有的衍生類的屬性的一起。由於DependencyObjectTypeDispatcher對象來自我繼承的DependencyObject類,如何添加智能標記或屬性(如[JsonIgnore])以防止它們被序列化?或者我可能想到這是錯誤的方式?如何防止使用Newtonsoft JSON對DependencyObjects上的DependencyObjectType信息進行序列化?

實例類代碼:

public class MyClass : DependencyObject 
{ 
    public int MyProperty 
    { 
     get { return (int)GetValue(MyPropertyProperty); } 
     set { SetValue(MyPropertyProperty, value); } 
    } 
    public static readonly DependencyProperty MyPropertyProperty = 
     DependencyProperty.Register("MyProperty", typeof(int), typeof(ownerclass), new PropertyMetadata(0)); 
} 

串行代碼:

JsonSerializer serializer = new JsonSerializer(); 
using (StreamWriter sw = new StreamWriter(filePath)) 
using (JsonWriter jw = new JsonTextWriter(sw)) 
{ 
    serializer.Serialize(jw, MyInstance); 
} 

當連載我得到這個龐大的BLOB(所有,但最上面一行是不需要的):

{ 
    "MyProperty": 0, 
    "DependencyObjectType": { 
     "Id": 148, 
     "SystemType": "MyProject.MyClass, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", 
     "BaseType": { 
     "Id": 0, 
     "SystemType": "System.Windows.DependencyObject, WindowsBase, Version=4.0.0.0, Culture=neutral, PublicKeyToken=xxx", 
     "BaseType": null, 
     "Name": "DependencyObject" 
     }, 
     "Name": "MyClass" 
    }, 
    "IsSealed": false, 
    "Dispatcher": { 
     "Thread": { 
     "ManagedThreadId": 17, 
     "ExecutionContext": null, 
     "Priority": 2, 
     "IsAlive": true, 
     "IsThreadPoolThread": true, 
     "IsBackground": true, 
     "ThreadState": 4, 
     "ApartmentState": 1, 
     "CurrentUICulture": "en-US", 
     "CurrentCulture": "en-US", 
     "Name": null 
     }, 
     "HasShutdownStarted": false, 
     "HasShutdownFinished": false, 
     "Hooks": {} 
    } 
} 

回答

3

你可以使用OptIn方法來抑制序列化在類型層次結構中的所有屬性,除了必需的屬性:

[JsonObject(MemberSerialization = MemberSerialization.OptIn)] 

和馬克屬性序列化帶:

[JsonProperty] 
1

@Filip's answer,說明你可以用MemberSerialization.OptIn[JsonProperty]標記您的類型。

的第二個答案是使用一個custom ContractResolver省略了指定的基類的所有屬性,或基類的集合:

/// <summary> 
/// Contract resolver to ignore properties of a single given type. 
/// </summary> 
/// <typeparam name="T"></typeparam> 
public class IgnoreTypePropertiesContractResolver<T> : IgnoreTypePropertiesContractResolver 
{ 
    // As of 7.0.1, Json.NET suggests using a static instance for "stateless" contract resolvers, for performance reasons. 
    // http://www.newtonsoft.com/json/help/html/ContractResolver.htm 
    // http://www.newtonsoft.com/json/help/html/M_Newtonsoft_Json_Serialization_DefaultContractResolver__ctor_1.htm 
    // "Use the parameterless constructor and cache instances of the contract resolver within your application for optimal performance." 
    static IgnoreTypePropertiesContractResolver<T> instance; 

    static IgnoreTypePropertiesContractResolver() { instance = new IgnoreTypePropertiesContractResolver<T>(); } 

    public static IgnoreTypePropertiesContractResolver<T> Instance { get { return instance; } } 

    IgnoreTypePropertiesContractResolver() : base(new[] { typeof(T) }) { } 
} 

/// <summary> 
/// Contract resolver to ignore properties of any number of given types. 
/// </summary> 
public class IgnoreTypePropertiesContractResolver : DefaultContractResolver 
{ 
    readonly HashSet<Type> toIgnore; 
    readonly HashSet<Type> toIgnoreAndBase; 

    public IgnoreTypePropertiesContractResolver(IEnumerable<Type> toIgnore) 
    { 
     if (toIgnore == null) 
      throw new ArgumentNullException(); 
     this.toIgnore = new HashSet<Type>(toIgnore); 
     this.toIgnoreAndBase = new HashSet<Type>(toIgnore.SelectMany(t => t.BaseTypesAndSelf())); 
    } 

    protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization) 
    { 
     var list = base.CreateProperties(type, memberSerialization); 
     if (type.BaseTypesAndSelf().Any(t => toIgnore.Contains(t))) 
     { 
      var filtered = list.Where(p => !toIgnoreAndBase.Contains(p.DeclaringType)).ToList(); 
      return filtered; 
     } 
     return list; 
    } 
} 

public static class TypeExtensions 
{ 
    public static IEnumerable<Type> BaseTypesAndSelf(this Type type) 
    { 
     while (type != null) 
     { 
      yield return type; 
      type = type.BaseType; 
     } 
    } 
} 

通過自定義合同解析器,沒有必要添加屬性每種類型。

然後序列如下:

var settings = new JsonSerializerSettings { ContractResolver = IgnoreTypePropertiesContractResolver<DependencyObject>.Instance }; 
var json = JsonConvert.SerializeObject(new MyClass { MyProperty = 101 }, settings); 
相關問題