2016-08-18 91 views
1

我有一堆C#類,其中很多都利用DefaultValueAttribute包含用於編輯目的的UI提示。有沒有辦法可以禁用DefaultValueAttributes的處理?

我使用Json.NET序列化這些類型的實例,並將它們發送到JavaScript客戶端。爲了優化帶寬,我想使用DefaultValueHandling.Ignore選項,但是考慮到它不佔用DefaultValueAttribute。換句話說,我想忽略技術默認值false, 0, null,但不是開發人員定義的默認值。

其原因是JavaScript客戶端不知道特殊的,開發人員定義的默認值,所以它只能處理上面提到的一般默認值。

有什麼方法可以使用DefaultValueAttribute s關閉?

+0

刪除了[tag:javascript]標記,問題純粹是關於C#方面的事情。 –

+0

我不確定我瞭解問題所在。 DefaultValueAttribute被設計爲供UI設計者使用 - 它實際上並沒有在底層類上設置任何默認值。它不應該被JsonSerializer序列化 - 你可以添加生成的Json流的片段,突出顯示數據中的問題請 – PhillipH

回答

1

您可以創建一個custom contract resolverDefaultContractResolverCamelCasePropertyNamesContractResolver繼承該重置contract default value的財產回default(T)

public class NoDefaultValueContractResolver : DefaultContractResolver 
{ 
    // 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 NoDefaultValueContractResolver instance; 

    // Explicit static constructor to tell C# compiler not to mark type as beforefieldinit 
    static NoDefaultValueContractResolver() { instance = new NoDefaultValueContractResolver(); } 

    public static NoDefaultValueContractResolver Instance { get { return instance; } } 

    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) 
    { 
     var property = base.CreateProperty(member, memberSerialization); 

     if (property.AttributeProvider.GetAttributes(typeof(DefaultValueAttribute), true).Any()) 
     { 
      property.DefaultValue = property.PropertyType.GetDefaultValue(); 
     } 
     return property; 
    } 
} 

public static class TypeExtensions 
{ 
    public static object GetDefaultValue(this Type type) 
    { 
     if (type == null) 
      throw new ArgumentNullException("type"); 
     if (!type.IsValueType || Nullable.GetUnderlyingType(type) != null) 
      return null; 
     return Activator.CreateInstance(type, true); 
    } 
} 

然後使用它像:

var settings = new JsonSerializerSettings { DefaultValueHandling = DefaultValueHandling.Ignore, ContractResolver = NoDefaultValueContractResolver.Instance }; 
var json = JsonConvert.SerializeObject(obj, settings); 

通過使用自定義的合同解析器您可以避免需要爲每個類型或成員創建轉換器,這些轉換器在某個地方有DefaultValueAttribute

+0

謝謝,這是一個不錯的解決方案。 –

0

有趣的是,Json.net使用DefaultValueAttribute--它的目的是爲視覺設計表面使用,而不是序列化。我會始終將其設置爲忽略。

如果您想要在序列化之前應用默認值,您應該在反序列化之前明確設置該值;您可以在將其發送到序列化程序之前,通過在類實例上使用反射來完成此操作。或者,您可以像這裏建議的那樣,How do you modify the Json serialization of just one field using Json.net?將反射和JsonConvert結合,在將值寫入串行器之前截取值。

相關問題