How to configure JSON.net deserializer to track missing properties?

前端 未结 3 1072

Sample class:

public class ClassA
{
    public int Id { get; set; }
    public string SomeString { get; set; }
    public int? SomeInt { get; set; }
}
         


        
3条回答
  •  忘掉有多难
    2020-12-18 08:43

    Another way to find null/undefined tokens during De-serialization is to write a custom JsonConverter , Here is an example of custom converter which can report both omitted tokens (e.g. "{ 'Id':5 }") and null tokens (e.g {"Id":5,"SomeString":null,"SomeInt":null})

    public class NullReportConverter : JsonConverter
    {
        private readonly List _nullproperties=new List();
        public bool ReportDefinedNullTokens { get; set; }
    
        public IEnumerable NullProperties
        {
            get { return _nullproperties; }
        }
    
        public void Clear()
        {
            _nullproperties.Clear();
        }
    
        public override bool CanConvert(Type objectType)
        {
            return true;
        }
    
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            existingValue = existingValue ?? Activator.CreateInstance(objectType, true);
    
            var jObject = JObject.Load(reader);
            var properties =
                objectType.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
    
            foreach (var property in properties)
            {
                var jToken = jObject[property.Name];
                if (jToken == null)
                {
                    _nullproperties.Add(property);
                    continue;
                }
    
                var value = jToken.ToObject(property.PropertyType);
                if(ReportDefinedNullTokens && value ==null)
                    _nullproperties.Add(property);
    
                property.SetValue(existingValue, value, null);
            }
    
            return existingValue;
        }
    
        //NOTE: we can omit writer part if we only want to use the converter for deserializing
        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            var objectType = value.GetType();
            var properties =
                objectType.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
    
            writer.WriteStartObject();
            foreach (var property in properties)
            {
                var propertyValue = property.GetValue(value, null);
                writer.WritePropertyName(property.Name);
                serializer.Serialize(writer, propertyValue);
            }
    
            writer.WriteEndObject();
        }
    }
    

    Note: we can omit the Writer part if we don't need to use it for serializing objects.

    Usage Example:

    class Foo
    {
        public int Id { get; set; }
        public string SomeString { get; set; }
        public int? SomeInt { get; set; }
    }
    
    class Program
    {
        static void Main(string[] args)
        {
            var nullConverter=new NullReportConverter();
    
            Console.WriteLine("Pass 1");
            var obj0 = JsonConvert.DeserializeObject("{\"Id\":5, \"Id\":5}", nullConverter);
            foreach(var p in nullConverter.NullProperties)
                Console.WriteLine(p);
    
            nullConverter.Clear();
    
            Console.WriteLine("Pass2");
            var obj1 = JsonConvert.DeserializeObject("{\"Id\":5,\"SomeString\":null,\"SomeInt\":null}" , nullConverter);
            foreach (var p in nullConverter.NullProperties)
                Console.WriteLine(p);
    
            nullConverter.Clear();
    
            nullConverter.ReportDefinedNullTokens = true;
            Console.WriteLine("Pass3");
            var obj2 = JsonConvert.DeserializeObject("{\"Id\":5,\"SomeString\":null,\"SomeInt\":null}", nullConverter);
            foreach (var p in nullConverter.NullProperties)
                Console.WriteLine(p);
        }
    }
    

提交回复
热议问题