2016-08-18 88 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结合,在将值写入串行器之前截取值。

相关问题