问题
I have some objects that I want to serialize as JSON. However, some of the objects have properties which are deemed 'SensitiveData' via attributes.
[SensitiveDataAttribute]
public string SomeSensitiveProperty {get; set;}
At the moment, I am overriding the 'CreateProperty' method on the serializer so that I can alter whether or not a property should be serialized dependent upon whether it has this 'SensitiveData' attribute:
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;
}
}
}
When I serialize, I then use that resolver as settings for the serializer:
var settings = new JsonSerializerSettings() { ContractResolver = new SensitiveDataResolver() };
var requestString = JsonConvert.SerializeObject(someObject, settings);
My problem is, I don't want the properties to be excluded from the serialization. I want them to be serialized but with the default value 'SensitiveData' set against them.
Is there a way I can achieve this using Attributes?
回答1:
Instead of using the ShouldSerialize
method, you can just override the property value if the member has the attribute. To do this, you need to supply a custom IValueProvider
for Json.NET to use when serializing.
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
is a custom implementation of the IValueProvider
interface.
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;
}
}
回答2:
Implement IValueProvider
for sensitive data property and use it for 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;
}
}
Now your DefaultContractResolver
would be:
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;
}
}
回答3:
Instead of setting property.ShouldSerialize you can overwrite the property value itself.
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;
}
}
回答4:
You could do this with reflection inside of your contract resolver.
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);
}
}
}
来源:https://stackoverflow.com/questions/33148957/replace-sensitive-data-value-on-json-serialization