diff --git a/Src/Newtonsoft.Json.Tests/Serialization/DefaultValueHandlingTests.cs b/Src/Newtonsoft.Json.Tests/Serialization/DefaultValueHandlingTests.cs index 5aff8ece..b2455d0a 100644 --- a/Src/Newtonsoft.Json.Tests/Serialization/DefaultValueHandlingTests.cs +++ b/Src/Newtonsoft.Json.Tests/Serialization/DefaultValueHandlingTests.cs @@ -228,6 +228,81 @@ namespace Newtonsoft.Json.Tests.Serialization ""IntDefault"": 0 }", json); } + + [Test] + public void DeserializeWithIgnore() + { + string json = @"{'Value':null,'IntValue1':1,'IntValue2':0,'IntValue3':null}"; + + var o = JsonConvert.DeserializeObject(json, new JsonSerializerSettings + { + DefaultValueHandling = DefaultValueHandling.Ignore + }); + + Assert.AreEqual(int.MaxValue, o.IntValue1); + Assert.AreEqual(int.MinValue, o.IntValue2); + Assert.AreEqual(int.MaxValue, o.IntValue3); + Assert.AreEqual("Derp!", o.ClassValue.Derp); + } + + [Test] + public void DeserializeWithPopulate() + { + string json = @"{}"; + + var o = JsonConvert.DeserializeObject(json, new JsonSerializerSettings + { + DefaultValueHandling = DefaultValueHandling.Populate + }); + + Assert.AreEqual(1, o.IntValue1); + Assert.AreEqual(0, o.IntValue2); + Assert.AreEqual(null, o.ClassValue); + } + } + + public class DefaultValueHandlingDeserialize + { + public string Derp { get; set; } + } + + public class DefaultValueHandlingDeserializeHolder + { + public DefaultValueHandlingDeserializeHolder() + { + ClassValue = new DefaultValueHandlingDeserialize + { + Derp = "Derp!" + }; + IntValue1 = int.MaxValue; + IntValue2 = int.MinValue; + IntValue3 = int.MaxValue; + } + + [DefaultValue(1)] + public int IntValue1 { get; set; } + public int IntValue2 { get; set; } + [DefaultValue(null)] + public int IntValue3 { get; set; } + public DefaultValueHandlingDeserialize ClassValue { get; set; } + } + + public class DefaultValueHandlingDeserializePopulate + { + public DefaultValueHandlingDeserializePopulate() + { + ClassValue = new DefaultValueHandlingDeserialize + { + Derp = "Derp!" + }; + IntValue1 = int.MaxValue; + IntValue2 = int.MinValue; + } + + [DefaultValue(1)] + public int IntValue1 { get; set; } + public int IntValue2 { get; set; } + public DefaultValueHandlingDeserialize ClassValue { get; set; } } public struct DefaultStruct diff --git a/Src/Newtonsoft.Json/Serialization/DefaultContractResolver.cs b/Src/Newtonsoft.Json/Serialization/DefaultContractResolver.cs index 9ef96c15..56aaf7ef 100644 --- a/Src/Newtonsoft.Json/Serialization/DefaultContractResolver.cs +++ b/Src/Newtonsoft.Json/Serialization/DefaultContractResolver.cs @@ -471,7 +471,10 @@ namespace Newtonsoft.Json.Serialization property.PropertyName = (property.PropertyName != parameterInfo.Name) ? property.PropertyName : matchingMemberProperty.PropertyName; property.Converter = property.Converter ?? matchingMemberProperty.Converter; property.MemberConverter = property.MemberConverter ?? matchingMemberProperty.MemberConverter; - property.DefaultValue = property.DefaultValue ?? matchingMemberProperty.DefaultValue; + + if (!property._hasExplicitDefaultValue && matchingMemberProperty._hasExplicitDefaultValue) + property.DefaultValue = matchingMemberProperty.DefaultValue; + property._required = property._required ?? matchingMemberProperty._required; property.IsReference = property.IsReference ?? matchingMemberProperty.IsReference; property.NullValueHandling = property.NullValueHandling ?? matchingMemberProperty.NullValueHandling; @@ -1011,7 +1014,8 @@ namespace Newtonsoft.Json.Serialization property.MemberConverter = JsonTypeReflector.GetJsonConverter(attributeProvider, property.PropertyType); DefaultValueAttribute defaultValueAttribute = JsonTypeReflector.GetAttribute(attributeProvider); - property.DefaultValue = (defaultValueAttribute != null) ? defaultValueAttribute.Value : null; + if (defaultValueAttribute != null) + property.DefaultValue = defaultValueAttribute.Value; property.NullValueHandling = (propertyAttribute != null) ? propertyAttribute._nullValueHandling : null; property.ReferenceLoopHandling = (propertyAttribute != null) ? propertyAttribute._referenceLoopHandling : null; diff --git a/Src/Newtonsoft.Json/Serialization/JsonProperty.cs b/Src/Newtonsoft.Json/Serialization/JsonProperty.cs index 5c39cbee..d9ca5dcc 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonProperty.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonProperty.cs @@ -24,6 +24,8 @@ #endregion using System; +using Newtonsoft.Json.Utilities; + #if NET20 using Newtonsoft.Json.Utilities.LinqBridge; #endif @@ -36,6 +38,8 @@ namespace Newtonsoft.Json.Serialization public class JsonProperty { internal Required? _required; + internal bool _hasExplicitDefaultValue; + internal object _defaultValue; // use to cache contract during deserialization internal JsonContract PropertyContract { get; set; } @@ -117,7 +121,26 @@ namespace Newtonsoft.Json.Serialization /// Gets the default value. /// /// The default value. - public object DefaultValue { get; set; } + public object DefaultValue + { + get + { + return _defaultValue; + } + set + { + _hasExplicitDefaultValue = true; + _defaultValue = value; + } + } + + internal object GetResolvedDefaultValue() + { + if (!_hasExplicitDefaultValue && PropertyType != null) + return ReflectionUtils.GetDefaultValue(PropertyType); + + return _defaultValue; + } /// /// Gets a value indicating whether this is required. diff --git a/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs b/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs index 819cd6f4..6fc3f9d0 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs @@ -737,7 +737,7 @@ To fix this error either change the JSON to a {1} or change the deserialized typ // test tokentype here because default value might not be convertable to actual type, e.g. default of "" for DateTime if (HasFlag(property.DefaultValueHandling.GetValueOrDefault(Serializer.DefaultValueHandling), DefaultValueHandling.Ignore) && JsonReader.IsPrimitiveToken(reader.TokenType) - && MiscellaneousUtils.ValueEquals(reader.Value, property.DefaultValue)) + && MiscellaneousUtils.ValueEquals(reader.Value, property.GetResolvedDefaultValue())) { reader.Skip(); return true; @@ -772,7 +772,7 @@ To fix this error either change the JSON to a {1} or change the deserialized typ return false; if (HasFlag(property.DefaultValueHandling.GetValueOrDefault(Serializer.DefaultValueHandling), DefaultValueHandling.Ignore) - && MiscellaneousUtils.ValueEquals(value, property.DefaultValue)) + && MiscellaneousUtils.ValueEquals(value, property.GetResolvedDefaultValue())) return false; if (!property.Writable) @@ -1572,7 +1572,7 @@ To fix this error either change the environment to be fully trusted, change the property.PropertyContract = GetContractSafe(property.PropertyType); if (HasFlag(property.DefaultValueHandling.GetValueOrDefault(Serializer.DefaultValueHandling), DefaultValueHandling.Populate) && property.Writable) - property.ValueProvider.SetValue(newObject, EnsureType(reader, property.DefaultValue, CultureInfo.InvariantCulture, property.PropertyContract, property.PropertyType)); + property.ValueProvider.SetValue(newObject, EnsureType(reader, property.GetResolvedDefaultValue(), CultureInfo.InvariantCulture, property.PropertyContract, property.PropertyType)); break; case PropertyPresence.Null: if (resolvedRequired == Required.Always) diff --git a/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs b/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs index cdfef01a..c1a4bdbf 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs @@ -205,7 +205,7 @@ namespace Newtonsoft.Json.Serialization return false; if (HasFlag(property.DefaultValueHandling.GetValueOrDefault(Serializer.DefaultValueHandling), DefaultValueHandling.Ignore) - && MiscellaneousUtils.ValueEquals(memberValue, property.DefaultValue ?? ReflectionUtils.GetDefaultValue(property.PropertyType))) + && MiscellaneousUtils.ValueEquals(memberValue, property.GetResolvedDefaultValue())) return false; return true;