0

I'm writing a custom json converter that will serialize an object and mask certain fields that contains some sensitive information. I've created the converter, but when I'm serializing the object using my converter, I'm getting an empty string. Can someone tell me what I'm doing wrong?

public class Student
{
    public string Name { get; set; }

    public string Phone { get; set; }
}

class StudentJsonConverter : JsonConverter
{
    /// <inheritdoc />
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        if (value is Student student)
        {
            student.Phone = MaskString(student.Phone);
        }

        writer.WriteStartObject();
        serializer.Serialize(writer, value);
        writer.WriteEndObject();
    }

    /// <inheritdoc />
    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }

    /// <inheritdoc />
    public override bool CanConvert(Type objectType) => typeof(Student) == objectType;

    private static string MaskString(string sensitiveInformation) => string.IsNullOrWhiteSpace(sensitiveInformation) ? null : new string('*', sensitiveInformation.Length);
}

And here I'm using it:

    JsonSerializerSettings settings = new JsonSerializerSettings();
    settings.Converters.Add(new StudentJsonConverter());
    settings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
    var student = new Student { Name = "name", Phone = "1234" };

    var serializedString = JsonConvert.SerializeObject(student, settings);

    Console.WriteLine(serializedString);

But I'm always getting an empty string.

Buda Gavril
  • 21,409
  • 40
  • 127
  • 196

1 Answers1

0

Please have a look at the Custom JsonConverter sample.

EDIT:

I think it would be better to post another question for the other issue in your comment, but anyway, I've played a bit and came out with the following code. I think it is far better than what I posted before, so I prefer removing my previous sample. The reason why this code seems far better to me is that it does not alter the Student object you are trying to serialize, but simply works on the JObject instance.

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
    Newtonsoft.Json.Linq.JToken t = Newtonsoft.Json.Linq.JToken.FromObject(value);
    JObject jo = (JObject)t;
    if (value is Student)
    {
        jo["Phone"] = MaskString(jo.Value<string>("Phone"));

        if (String.IsNullOrEmpty(jo.Value<string>("Name")))
        {
            jo.Remove("Name");
        }
    }
    serializer.Serialize(writer, jo, typeof(Student));
}
PSkalka
  • 137
  • 5
  • This almost works. But If I'm adding to my json settings settings.NullValueHandling = NullValueHandling.Ignore; and set the property Name to null, this property will be serialized. Do you know how to fix this? – Buda Gavril May 29 '18 at 15:29
  • but isn't there a way to do it without manually writing each property? Because by doing this, when I will add a property to my model, I will have to update the converter... – Buda Gavril May 30 '18 at 06:18
  • You could make the code more dynamic by parsing the properties collection of JObject and acting on them; another option would be using the NewtonSoft attributes (like JsonIgnore or its alikes), or even defining your own custom attributes and applying them to the model, then reading them in the WriteJson method to decide what to do. Anyway, as @Optional Option suggested, you could simplify a lot, just ignoring some properties. I really see no functional gain in serializing masked properties rather than omitting them. – PSkalka May 30 '18 at 07:09