From 70521eea88c7e6a24c0446b9e0d20617c9a6fad2 Mon Sep 17 00:00:00 2001 From: James Newton-King Date: Sat, 13 Jun 2015 22:31:16 +1200 Subject: [PATCH] -Fixed empty strings coerced to null not erroring with Required.Always --- .../Serialization/JsonSerializerTest.cs | 15 +++++++ .../Serialization/TypeNameHandlingTests.cs | 1 - .../JsonSerializerInternalReader.cs | 39 +++++++++++++------ 3 files changed, 42 insertions(+), 13 deletions(-) diff --git a/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs b/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs index 509071cb..bead7fb8 100644 --- a/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs +++ b/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs @@ -95,6 +95,21 @@ namespace Newtonsoft.Json.Tests.Serialization [TestFixture] public class JsonSerializerTest : TestFixtureBase { + [Test] + public void CoercedEmptyStringWithRequired() + { + ExceptionAssert.Throws(() => + { + JsonConvert.DeserializeObject("{requiredProperty:''}"); + }, "Required property 'RequiredProperty' expects a value but got null. Path '', line 1, position 21."); + } + + public class Binding + { + [JsonProperty(Required = Required.Always)] + public Binding RequiredProperty { get; set; } + } + public class DictionaryKeyContractResolver : DefaultContractResolver { protected override string ResolveDictionaryKey(string dictionaryKey) diff --git a/Src/Newtonsoft.Json.Tests/Serialization/TypeNameHandlingTests.cs b/Src/Newtonsoft.Json.Tests/Serialization/TypeNameHandlingTests.cs index b0930963..63553aaf 100644 --- a/Src/Newtonsoft.Json.Tests/Serialization/TypeNameHandlingTests.cs +++ b/Src/Newtonsoft.Json.Tests/Serialization/TypeNameHandlingTests.cs @@ -2122,5 +2122,4 @@ namespace Newtonsoft.Json.Tests.Serialization } #endif } - #endif \ No newline at end of file diff --git a/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs b/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs index 455e1597..f3ee071f 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs @@ -279,7 +279,7 @@ namespace Newtonsoft.Json.Serialization string s = (string)reader.Value; // convert empty string to null automatically for nullable types - if (string.IsNullOrEmpty(s) && objectType != null && objectType != typeof(string) && objectType != typeof(object) && contract != null && contract.IsNullable) + if (CoerceEmptyStringToNull(objectType, contract, s)) return null; // string that needs to be returned as a byte array should be base 64 decoded @@ -312,6 +312,11 @@ namespace Newtonsoft.Json.Serialization throw JsonSerializationException.Create(reader, "Unexpected end when deserializing object."); } + private static bool CoerceEmptyStringToNull(Type objectType, JsonContract contract, string s) + { + return string.IsNullOrEmpty(s) && objectType != null && objectType != typeof(string) && objectType != typeof(object) && contract != null && contract.IsNullable; + } + internal string GetExpectedDescription(JsonContract contract) { switch (contract.ContractType) @@ -1804,9 +1809,6 @@ namespace Newtonsoft.Json.Serialization if (!property.Ignored) { - if (property.PropertyContract == null) - property.PropertyContract = GetContractSafe(property.PropertyType); - object propertyValue; if (propertyConverter != null && propertyConverter.CanRead) propertyValue = DeserializeConvertable(propertyConverter, reader, property.PropertyType, null); @@ -1986,15 +1988,13 @@ namespace Newtonsoft.Json.Serialization continue; } + if (property.PropertyContract == null) + property.PropertyContract = GetContractSafe(property.PropertyType); + JsonConverter propertyConverter = null; if (!property.Ignored) - { - if (property.PropertyContract == null) - property.PropertyContract = GetContractSafe(property.PropertyType); - propertyConverter = GetConverter(property.PropertyContract, property.MemberConverter, contract, member); - } if (!ReadForType(reader, property.PropertyContract, propertyConverter != null)) throw JsonSerializationException.Create(reader, "Unexpected end when setting {0}'s value.".FormatWith(CultureInfo.InvariantCulture, memberName)); @@ -2124,9 +2124,24 @@ namespace Newtonsoft.Json.Serialization { if (property != null && requiredProperties != null) { - requiredProperties[property] = (reader.TokenType == JsonToken.Null || reader.TokenType == JsonToken.Undefined) - ? PropertyPresence.Null - : PropertyPresence.Value; + PropertyPresence propertyPresence; + switch (reader.TokenType) + { + case JsonToken.String: + propertyPresence = (CoerceEmptyStringToNull(property.PropertyType, property.PropertyContract, (string)reader.Value)) + ? PropertyPresence.Null + : PropertyPresence.Value; + break; + case JsonToken.Null: + case JsonToken.Undefined: + propertyPresence = PropertyPresence.Null; + break; + default: + propertyPresence = PropertyPresence.Value; + break; + } + + requiredProperties[property] = propertyPresence; } }