-Fixed empty strings coerced to null not erroring with Required.Always

This commit is contained in:
James Newton-King
2015-06-13 22:31:16 +12:00
parent b270104bfb
commit 70521eea88
3 changed files with 42 additions and 13 deletions
@@ -95,6 +95,21 @@ namespace Newtonsoft.Json.Tests.Serialization
[TestFixture]
public class JsonSerializerTest : TestFixtureBase
{
[Test]
public void CoercedEmptyStringWithRequired()
{
ExceptionAssert.Throws<JsonSerializationException>(() =>
{
JsonConvert.DeserializeObject<Binding>("{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)
@@ -2122,5 +2122,4 @@ namespace Newtonsoft.Json.Tests.Serialization
}
#endif
}
#endif
@@ -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;
}
}