2016-06-23 86 views
0

我有一個自定義類,看起來像這樣:Json.NET:如何使DefaultValueHandling僅適用於某些類型?

public class PartnerLoginOptions 
{ 
    public string Username { get; set; } 
    public string Password { get; set; } 
    public string DeviceModel { get; set; } 
    public string Version { get; set; } 

    public bool? IncludeUrls { get; set; } 
    public bool? ReturnDeviceType { get; set; } 
    public bool? ReturnUpdatePromptVersions { get; set; } 
} 

我想忽略任何bool?成員默認值序列化時,卻保持字符串與空值。舉例來說,如果我有這樣的

var options = new PartnerLoginOptions 
{ 
    Username = null, 
    Password = "123", 
    IncludeUrls = null, 
    ReturnDeviceType = true 
}; 

一個對象,然後序列化會導致這樣的:

{ 
    "username": null, 
    "password": "123", 
    "deviceModel": null, 
    "version": null, 
    "returnDeviceType": true 
} 

這裏是我的代碼至今:

var settings = new JsonSerializerSettings 
{ 
    ContractResolver = new CamelCasePropertyNamesContractResolver(), 
    DefaultValueHandling = DefaultValueHandling.Ignore // this applies to strings too, not just bool? 
}; 

return JsonConvert.SerializeObject(options, settings); 

有什麼方式做到這一點,沒有單獨標記OptionalBool財產與[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]?謝謝。

回答

2

您可以創建一個custom contract resolver繼承自DefaultContractResolver,它將DefaultValueHandling.Ignore應用於所需類型的所有屬性。但是,您的具體問題有一些限制:

  1. 要應用的默認值處理到系統類型,即bool?。因此,合同解析器不能通過對該類型應用一些自定義屬性來實現,然後在CreateProperty()中檢查它。相反,有必要將一組覆蓋項傳遞給合同解析器的構造函數。您正在使用CamelCasePropertyNamesContractResolver。如果您繼承它並將不同的覆蓋列表傳遞給不同的實例,您將遇到this question中的錯誤,即在每個子類型的所有實例中強制共享合同,即使不同的實例會以其他方式返回不同的合同。因此有必要繼承DefaultContractResolver,它沒有這個bug。

因此你的合同解析器應該是這樣的:

public class DefaultValueCamelCaseContractResolver : DefaultValueContractResolver 
{ 
    public DefaultValueCamelCaseContractResolver(IEnumerable<KeyValuePair<Type, DefaultValueHandling>> overrides) : base(overrides) { } 

    protected override string ResolvePropertyName(string propertyName) 
    { 
     return propertyName.ToCamelCase(); 
    } 
} 

public class DefaultValueContractResolver : DefaultContractResolver 
{ 
    readonly Dictionary<Type, DefaultValueHandling> overrides; 

    public DefaultValueContractResolver(IEnumerable<KeyValuePair<Type, DefaultValueHandling>> overrides) 
     : base() 
    { 
     if (overrides == null) 
      throw new ArgumentNullException("overrides"); 
     this.overrides = overrides.ToDictionary(p => p.Key, p => p.Value); 
    } 

    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) 
    { 
     var property = base.CreateProperty(member, memberSerialization); 
     if (property.DefaultValueHandling == null) 
     { 
      DefaultValueHandling handling; 
      if (overrides.TryGetValue(property.PropertyType, out handling)) 
       property.DefaultValueHandling = handling; 
     } 

     return property; 
    } 
} 

public static class CamelCaseNameExtensions 
{ 
    class CamelCaseNameResolver : CamelCasePropertyNamesContractResolver 
    { 
     // Explicit static constructor to tell C# compiler not to mark type as beforefieldinit 
     static CamelCaseNameResolver() { } 
     internal static readonly CamelCaseNameResolver Instance = new CamelCaseNameResolver(); 

     // Purely to make the protected method public. 
     public string ToCamelCase(string propertyName) 
     { 
      return ResolvePropertyName(propertyName); 
     } 
    } 

    public static string ToCamelCase(this string propertyName) 
    { 
     if (propertyName == null) 
      return null; 
     return CamelCaseNameResolver.Instance.ToCamelCase(propertyName); 
    } 
} 

然後使用它像:

var options = new PartnerLoginOptions 
{ 
    Username = null, 
    Password = "123", 
    IncludeUrls = null, 
    ReturnDeviceType = true 
}; 

var settings = new JsonSerializerSettings 
{ 
    ContractResolver = new DefaultValueCamelCaseContractResolver(new Dictionary<Type, DefaultValueHandling> { { typeof(bool?), DefaultValueHandling.Ignore } }), 
}; 

var json = JsonConvert.SerializeObject(options, Formatting.Indented, settings); 

需要注意的是,如果你有一個類型的標準列表,您可以隨時申請一個默認值處理覆蓋,你應該cache an instance of the contract resolver獲得最佳性能。

相關問題