Newtonsoft JsonConvert.DeserializeObject how to ignore empty objects

Viewed 3787

I have the following class definitions:

public class Tag
{
    public Guid? TagId { get; set; }
    public string TagText { get; set; }
    public DateTime CreatedOn { get; set; }
}

public class Wiki
{
    public Guid? WikiId { get; set; }
    public string WikiText { get; set; }
    public string Title { get; set; }
    public DateTime CreatedOn { get; set; }
    public IEnumerable<Tag> Tags { get; set; }
}

From the database i get the following json Object:

{
    "WikiId": "83981284-0AD3-4420-90AB-15E3BF6BD7B7",
    "WikiText": "Text",
    "Title": "Title",
    "CreatedOn": "2017-08-07T09:16:06.0800000",
    "Tags": [{}] // <-- here i would like to ignore the empty Tag object
}

When i do now a JsonConvert.DeserializeObject<Wiki>(json) i get a Wiki object with a list of 1 Tag with the values TagId: null, TagText: null and CreatedOn: "0001-01-01T00:00:00"

Is there a way to ignore the empty Tag object while deserializing? I have tried several JsonSerializerSettings but nothing helped.

3 Answers

Thanks to @Brian-Rogers's brilliant answer, I was able to come up with a non-generic solution which will work on all collections instead of List only:

public class IgnoreEmptyArrayItemsConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        bool result = typeof(System.Collections.IEnumerable).IsAssignableFrom(objectType);
        return result;
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        var tokenIndexesToRemove = new List<int>();

        var array = JArray.Load(reader);

        for (int i = 0; i < array.Count; i++)
        {
            var obj = array[i];
            if (!obj.HasValues)
                tokenIndexesToRemove.Add(i);
        }

        foreach (int index in tokenIndexesToRemove)
            array.RemoveAt(index);

        var result = array.ToObject(objectType, serializer);
        return result;
    }

    public override bool CanWrite
    {
        get { return false; }
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

Instead of looping through the objects, deserializing them and adding them to a hardcoded List collection one by one, this solution will just remove the faulting tokens from the JArray and let the library deserialize the whole array to the type it should be.

Usage:

public class Wiki
{
    ...
    [JsonConverter(typeof(IgnoreEmptyItemsConverter))] // No generic parameter needed
    public HashSet<Tag> Tags { get; set; }
}

Fiddle: https://dotnetfiddle.net/9FCcpD

Related