替换JSON序列化中的敏感数据值

本文关键字:敏感数据 JSON 序列化 替换 | 更新日期: 2023-09-27 18:17:47

我有一些对象,我想序列化为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'。

有一种方法,我可以实现这使用属性?

替换JSON序列化中的敏感数据值

不使用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;
}

StringValueProviderIValueProvider接口的自定义实现。

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);
          }
     }
}