0

I have a poco class containing PersonalData, like this:

public class UserInfo
{
    [PersonalData]
    public string Name { get; set; }

    [PersonalData]
    public string Address { get; set; }

    [PersonalData]
    public DateTime Dob { get; set; }

    public bool IsActive { get; set; }
}

I have many scenario's I serialize this object and what I'd like to do is mask the Pii data like this "****" during the serialization process - I'm serializing this to write to logs for example.

I've attempted to implement my own serializer with this code:

public class PersonalDataSerializer<T> : JsonConverter<T> 
    where T: new()
{
    public override bool CanConvert(Type typeToConvert)
    {
        return typeToConvert.HasPiiData();
    }

    public override T Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        // read here...
        throw new NotImplementedException();
    }

    public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options)
    {
        // write here...
        throw new NotImplementedException();
    }
}

I'm not sure how to implement the write method without just carrying out normal serialization then trying to work out properties with the attribute and doing some sort of string manipulation.

What would make this easier is if the custom implementation was on each property instead of the whole object.

I use this method to identify properties on a type that have the PersonalData attribute:

public static class TypeExtensions
{
    public static bool HasPiiData(this Type type)
    {
        return type.GetProperties().Any(p => p.IsPiiData());
    }

    public static bool IsPiiData(this PropertyInfo prop)
    {
        foreach (var att in prop.CustomAttributes)
        {
            if (att.AttributeType == typeof(PersonalDataAttribute))
            {
                return true;
            }
            if (att.AttributeType.Name.Contains("PersonalData"))
            {
                return true;
            }
        }

        return false;
    }
}

Any advice on how to implement custom serialization based on an attribute would be much appreciated :-)

Rob
  • 6,819
  • 17
  • 71
  • 131
  • You should use a [custom contract resolver](https://www.newtonsoft.com/json/help/html/contractresolver.htm#CustomIContractResolverExamples) not a converter. See [Replace sensitive data value on JSON serialization](https://stackoverflow.com/q/33148957/3744182) which looks to be a duplicate. – dbc Nov 18 '20 at 23:44
  • 2
    It looks like you are using `System.Text.Json` based on the method signatures in the converter. Are you locked into that library, or can you switch to Newtonsoft.Json (Json.Net)? – Brian Rogers Nov 18 '20 at 23:51
  • Newtownsoft would probably be better actually due to 3.1 compatibility – Rob Nov 19 '20 at 00:08
  • Oh that's `System.Text.Json` not Json.NET. I can't think of any way to do this easily in `System.Text.Json` since it's equivalent to Json.NET's contract resolver is internal. See [System.Text.Json API is there something like IContractResolver](https://stackoverflow.com/q/58926112/3744182). – dbc Nov 19 '20 at 00:11
  • 1
    If you can switch to Newtonsoft then see the answer @dbc linked to in his first comment, or look at [How can I encrypt selected properties when serializing my objects?](https://stackoverflow.com/q/29196809/10263) for examples of using a Contract Resolver to solve a similar problem. Or see [How to mask sensitive values in JSON for logging purposes](https://stackoverflow.com/q/37821298/10263) for a different approach using Newtonsoft's LINQ-to-JSON API. – Brian Rogers Nov 19 '20 at 00:24

0 Answers0