我有一些对象,我想序列化为JSON。然而,一些对象的属性通过属性被认为是'SensitiveData'。
[SensitiveDataAttribute]
public string SomeSensitiveProperty {get; set;}
目前,我正在重写序列化器上的'CreateProperty'方法,以便我可以根据它是否具有这个'SensitiveData'属性来更改属性是否应该序列化:
public class SensitiveDataResolver : DefaultContractResolver
{
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
var property = base.CreateProperty(member, memberSerialization);
property.ShouldSerialize = instance =>
{
if (member is PropertyInfo)
{
var prop = (PropertyInfo) member;
var isSensitiveData = Attribute.IsDefined(prop, typeof (SensitiveDataAttribute));
return !isSensitiveData;
}
return false;
};
return property;
}
}
}
当我序列化时,我使用该解析器作为序列化器的设置:
var settings = new JsonSerializerSettings() { ContractResolver = new SensitiveDataResolver() };
var requestString = JsonConvert.SerializeObject(someObject, settings);
我的问题是,我不希望属性被排除在序列化之外。我希望它们被序列化,但对它们设置默认值'SensitiveData'。
有一种方法,我可以实现这使用属性?
不使用ShouldSerialize
方法,您可以在成员具有该属性时重写该属性值。为此,需要为Json提供自定义IValueProvider
。. NET序列化时使用。
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
var property = base.CreateProperty(member, memberSerialization);
if (member is PropertyInfo)
{
var prop = (PropertyInfo)member;
var isSensitiveData = Attribute.IsDefined(prop, typeof (SensitiveDataAttribute));
if (isSensitiveData)
property.ValueProvider = new StringValueProvider("SensitiveData");
}
return property;
}
StringValueProvider
是IValueProvider
接口的自定义实现。
public class StringValueProvider : IValueProvider
{
private readonly string _value;
public StringValueProvider(string value)
{
_value = value;
}
public void SetValue(object target, object value)
{
throw new NotSupportedException();
}
public object GetValue(object target)
{
return _value;
}
}
为敏感数据属性实现IValueProvider
并将其用于PropertyValueProvider。
public class SensitiveDataProvider : IValueProvider
{
readonly string sesitiveDatatag = "Sensitive Data";
public object GetValue(object target)
{
return sesitiveDatatag;
}
public void SetValue(object target, object value)
{
target = sesitiveDatatag;
}
}
现在你的DefaultContractResolver
将是:
public class SensitiveDataResolver : DefaultContractResolver
{
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
var property = base.CreateProperty(member, memberSerialization);
if (member is PropertyInfo)
{
var prop = (PropertyInfo)member;
var isSensitiveData = Attribute.IsDefined(prop, typeof(SensitiveDataAttribute));
if(isSensitiveData)
{
property.ValueProvider = new SensitiveDataProvider();
}
}
return property;
}
}
而不是设置属性。ShouldSerialize可以覆盖属性值本身。
public class SensitiveDataResolver : DefaultContractResolver
{
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
if (this.IsSensitiveProperty(member))
{
((PropertyInfo)member).SetValue(member, "SensitiveData", null);
}
var property = base.CreateProperty(member, memberSerialization);
return property;
}
private bool IsSensitiveProperty(MemberInfo member)
{
if (member is PropertyInfo)
{
var prop = (PropertyInfo) member;
var isSensitiveData = Attribute.IsDefined(prop, typeof (SensitiveDataAttribute));
return isSensitiveData;
}
return false;
}
}
你可以在你的契约解析器中使用反射。
PropertyInfo[] props = typeof(instanceOfMyClass).GetProperties();
foreach (PropertyInfo prop in props)
{
object[] attrs = prop.GetCustomAttributes(true);
foreach (object attr in attrs)
{
var sensitive = attr as SensitiveDataAttribute;
if (sensitive != null)
{
//add the default value to your property here
prop.SetValue(instanceOfMyClass, "Default Value", null);
}
}
}