2016-06-23 67 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获得最佳性能。

相关问题