For the project at work, we have these dynamic document forms each has their own model that Json string data posted back from the front end will be deserialised into. We don’t want to manually trim all the properties in each model when we consume them, so we thought we’d add a custom Json converter to automatically trim all the values coming in.
To add a custom converter for Newtonsoft.Json, simply implement the JsonConverter. We want to trim the value for only deserialisation so we only set the CanRead property to true and only implement the ReadJson method.
public class TrimmingJsonConverter : JsonConverter
{
public override bool CanRead => true;
public override bool CanWrite => false;
public override bool CanConvert(Type objectType) => objectType == typeof(string);
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
return ((string)reader.Value)?.Trim();
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
The following unit test to check if this works as expected
public class Book
{
public string Reference { get; set; }
public string Volume => Reference.Split("/")[0];
public string Folio => Reference.Split("/")[1];
public string Name { get; set; }
public DateTime PublishedDate { get; set; }
public override string ToString()
{
return $"{Volume}/{Folio}";
}
}
[Test]
public void TrimmingJsonConverter_Should_Auto_Trim_Value_When_Deserialised()
{
// Arrange
var data = "{ \"Name\":\" ABC \", \"PublishedDate\":\" 2020-01-29 \" }";
// Act
var book = JsonConvert.DeserializeObject<Book>(data,
new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Ignore,
Converters = new[] { new TrimmingJsonConverter() }
});
// Assert
book.Name.Should().Be("ABC");
book.PublishedDate.Should().Be(new DateTime(2020, 1, 29));
}