Search code examples
c#json.netjson-deserialization

C# How can I deserialize a List<T> with condition using Newtonsoft.Json


I have this classes:

public class CTest
{
  public int Id { get; set; }
  public string Name { get; set; }
  public List<Class2> Details { get; set; }
}

public class Class2
{
  public int Id { get; set; }
  public int Data1 { get; set; }
}

I know that I can deserialize using JsonConvert.DeserializeObject<T>(myObject); even Lists, but in Class2, I'd like to know how to filter if Id > 0.

For example, I'd like to get this result:

{
  "id":5,
  "name":"test",
  "details":[
    {
      "id":1,
      "data1":0.25
    }
  ]
}

Instead of:

{
  "id":5,
  "name":"test",
  "details":[
    {
      "id":12,
      "data1":0.25
    },
    {
      "id":0,
      "data1":0.0
    },
  ]
}

Solution

  • You can use Custom JsonConverter

    class ListClass2Converter : JsonConverter<List<Class2>>
    {
        public override List<Class2> ReadJson(JsonReader reader, Type objectType,
            [AllowNull] List<Class2> existingValue, bool hasExistingValue,
            JsonSerializer serializer)
        {            
            var list = new List<Class2>();
    
            while (reader.Read() && reader.TokenType != JsonToken.EndArray)
            {
                if (reader.TokenType == JsonToken.StartObject)
                {
                    var item = serializer.Deserialize<Class2>(reader);
                    if (item.Id != 0)
                        list.Add(item);
                }
            }
            return list;
        }
    
        public override void WriteJson(JsonWriter writer, [AllowNull] List<Class2> value,
            JsonSerializer serializer)
        {            
            serializer.Serialize(writer, ((List<Class2>)value).Where(c => c.Id != 0).ToArray());
        }
    }
    

    Read code

    var json = File.ReadAllText("test.json");
    var сTest = JsonConvert.DeserializeObject<CTest>(json, new ListClass2Converter());
    

    Write code

    var json = JsonConvert.SerializeObject(
        cTest, Formatting.Indented, new ListClass2Converter());
    

    You can use as many converters for different types of collections as you need.