diff --git a/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Compact.csproj b/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Compact.csproj index e70648aa..ee840945 100644 --- a/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Compact.csproj +++ b/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Compact.csproj @@ -74,6 +74,7 @@ + diff --git a/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Net20.csproj b/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Net20.csproj index 1d9ca0e7..9ec36bd5 100644 --- a/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Net20.csproj +++ b/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Net20.csproj @@ -74,6 +74,7 @@ + diff --git a/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Silverlight.csproj b/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Silverlight.csproj index 9f3e67a6..2dc60595 100644 --- a/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Silverlight.csproj +++ b/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Silverlight.csproj @@ -80,6 +80,7 @@ + diff --git a/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.csproj b/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.csproj index 82cb273e..72dffd54 100644 --- a/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.csproj +++ b/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.csproj @@ -110,6 +110,7 @@ + diff --git a/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs b/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs index a0d0dcbe..cb0c870c 100644 --- a/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs +++ b/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs @@ -406,73 +406,6 @@ keyword such as type of business."" CollectionAssert.AreEqual(r1, r2); } - [Test] - [ExpectedException(typeof(JsonSerializationException), ExpectedMessage = @"Could not find member 'Price' on object of type 'ProductShort'")] - public void MissingMemberDeserialize() - { - Product product = new Product(); - - product.Name = "Apple"; - product.ExpiryDate = new DateTime(2008, 12, 28); - product.Price = 3.99M; - product.Sizes = new string[] { "Small", "Medium", "Large" }; - - string output = JsonConvert.SerializeObject(product); - //{ - // "Name": "Apple", - // "ExpiryDate": new Date(1230422400000), - // "Price": 3.99, - // "Sizes": [ - // "Small", - // "Medium", - // "Large" - // ] - //} - - ProductShort deserializedProductShort = (ProductShort)JsonConvert.DeserializeObject(output, typeof(ProductShort), new JsonSerializerSettings { MissingMemberHandling = MissingMemberHandling.Error }); - } - - [Test] - public void MissingMemberDeserializeOkay() - { - Product product = new Product(); - - product.Name = "Apple"; - product.ExpiryDate = new DateTime(2008, 12, 28); - product.Price = 3.99M; - product.Sizes = new string[] { "Small", "Medium", "Large" }; - - string output = JsonConvert.SerializeObject(product); - //{ - // "Name": "Apple", - // "ExpiryDate": new Date(1230422400000), - // "Price": 3.99, - // "Sizes": [ - // "Small", - // "Medium", - // "Large" - // ] - //} - - JsonSerializer jsonSerializer = new JsonSerializer(); - jsonSerializer.MissingMemberHandling = MissingMemberHandling.Ignore; - - object deserializedValue; - - using (JsonReader jsonReader = new JsonTextReader(new StringReader(output))) - { - deserializedValue = jsonSerializer.Deserialize(jsonReader, typeof(ProductShort)); - } - - ProductShort deserializedProductShort = (ProductShort)deserializedValue; - - Assert.AreEqual("Apple", deserializedProductShort.Name); - Assert.AreEqual(new DateTime(2008, 12, 28), deserializedProductShort.ExpiryDate); - Assert.AreEqual("Small", deserializedProductShort.Sizes[0]); - Assert.AreEqual("Medium", deserializedProductShort.Sizes[1]); - Assert.AreEqual("Large", deserializedProductShort.Sizes[2]); - } - #if !PocketPC && !NET20 [Test] public void Unicode() @@ -1041,20 +974,6 @@ keyword such as type of business."" Assert.AreEqual(true, userNullablleDeserialized.Active); } - [Test] - public void MissingMemberIgnoreComplexValue() - { - JsonSerializer serializer = new JsonSerializer { MissingMemberHandling = MissingMemberHandling.Ignore }; - serializer.Converters.Add(new JavaScriptDateTimeConverter()); - - string response = @"{""PreProperty"":1,""DateProperty"":new Date(1225962698973),""PostProperty"":2}"; - - MyClass myClass = (MyClass)serializer.Deserialize(new StringReader(response), typeof(MyClass)); - - Assert.AreEqual(1, myClass.PreProperty); - Assert.AreEqual(2, myClass.PostProperty); - } - [Test] public void DeserializeInt64ToNullableDouble() { @@ -1064,15 +983,6 @@ keyword such as type of business."" Assert.AreEqual(1, c.Height); } - [Test] - [ExpectedException(typeof(JsonSerializationException), ExpectedMessage = "Could not find member 'Missing' on object of type 'DoubleClass'")] - public void MissingMemeber() - { - string json = @"{""Missing"":1}"; - - JsonConvert.DeserializeObject(json, new JsonSerializerSettings { MissingMemberHandling = MissingMemberHandling.Error }); - } - [Test] public void SerializeTypeProperty() { @@ -1089,12 +999,12 @@ keyword such as type of business."" public void RequiredMembersClass() { RequiredMembersClass c = new RequiredMembersClass() - { - BirthDate = new DateTime(2000, 12, 20, 10, 55, 55, DateTimeKind.Utc), - FirstName = "Bob", - LastName = "Smith", - MiddleName = "Cosmo" - }; + { + BirthDate = new DateTime(2000, 12, 20, 10, 55, 55, DateTimeKind.Utc), + FirstName = "Bob", + LastName = "Smith", + MiddleName = "Cosmo" + }; string json = JsonConvert.SerializeObject(c, Formatting.Indented); @@ -1111,6 +1021,21 @@ keyword such as type of business."" Assert.AreEqual(new DateTime(2000, 12, 20, 10, 55, 55, DateTimeKind.Utc), c2.BirthDate); } + [Test] + public void RequiredMembersClassWithNullValues() + { + string json = @"{ + ""FirstName"": null, + ""MiddleName"": null, + ""LastName"": null, + ""BirthDate"": ""\/Date(977309755000)\/"" +}"; + + RequiredMembersClass c = JsonConvert.DeserializeObject(json); + + Assert.AreEqual(null, c.FirstName); + } + [Test] [ExpectedException(typeof(JsonSerializationException), ExpectedMessage = "Required property 'LastName' not found in JSON.")] public void RequiredMembersClassMissingRequiredProperty() @@ -2229,14 +2154,14 @@ keyword such as type of business."" } [Test] - public void sdfsdf() + public void DeserializeNullableListWithNulls() { - //List l = new List(); - //l.Add(null); - //IList il = l; - //il.Add(null); + List l = JsonConvert.DeserializeObject>("[ 3.3, null, 1.1 ] "); + Assert.AreEqual(3, l.Count); - JsonConvert.DeserializeObject>("[ 3.3, null, 1.1 ] "); + Assert.AreEqual(3.3m, l[0]); + Assert.AreEqual(null, l[1]); + Assert.AreEqual(1.1m, l[2]); } } } \ No newline at end of file diff --git a/Src/Newtonsoft.Json.Tests/Serialization/MissingMemberHandlingTests.cs b/Src/Newtonsoft.Json.Tests/Serialization/MissingMemberHandlingTests.cs new file mode 100644 index 00000000..3e2b2fae --- /dev/null +++ b/Src/Newtonsoft.Json.Tests/Serialization/MissingMemberHandlingTests.cs @@ -0,0 +1,137 @@ +#region License +// Copyright (c) 2007 James Newton-King +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +#endregion + +using System; +using System.IO; +using Newtonsoft.Json.Converters; +using Newtonsoft.Json.Tests.TestObjects; +using NUnit.Framework; + +namespace Newtonsoft.Json.Tests.Serialization +{ + public class MissingMemberHandlingTests : TestFixtureBase + { + [Test] + [ExpectedException(typeof(JsonSerializationException), ExpectedMessage = @"Could not find member 'Price' on object of type 'ProductShort'")] + public void MissingMemberDeserialize() + { + Product product = new Product(); + + product.Name = "Apple"; + product.ExpiryDate = new DateTime(2008, 12, 28); + product.Price = 3.99M; + product.Sizes = new string[] { "Small", "Medium", "Large" }; + + string output = JsonConvert.SerializeObject(product); + //{ + // "Name": "Apple", + // "ExpiryDate": new Date(1230422400000), + // "Price": 3.99, + // "Sizes": [ + // "Small", + // "Medium", + // "Large" + // ] + //} + + ProductShort deserializedProductShort = (ProductShort)JsonConvert.DeserializeObject(output, typeof(ProductShort), new JsonSerializerSettings { MissingMemberHandling = MissingMemberHandling.Error }); + } + + [Test] + public void MissingMemberDeserializeOkay() + { + Product product = new Product(); + + product.Name = "Apple"; + product.ExpiryDate = new DateTime(2008, 12, 28); + product.Price = 3.99M; + product.Sizes = new string[] { "Small", "Medium", "Large" }; + + string output = JsonConvert.SerializeObject(product); + //{ + // "Name": "Apple", + // "ExpiryDate": new Date(1230422400000), + // "Price": 3.99, + // "Sizes": [ + // "Small", + // "Medium", + // "Large" + // ] + //} + + JsonSerializer jsonSerializer = new JsonSerializer(); + jsonSerializer.MissingMemberHandling = MissingMemberHandling.Ignore; + + object deserializedValue; + + using (JsonReader jsonReader = new JsonTextReader(new StringReader(output))) + { + deserializedValue = jsonSerializer.Deserialize(jsonReader, typeof(ProductShort)); + } + + ProductShort deserializedProductShort = (ProductShort)deserializedValue; + + Assert.AreEqual("Apple", deserializedProductShort.Name); + Assert.AreEqual(new DateTime(2008, 12, 28), deserializedProductShort.ExpiryDate); + Assert.AreEqual("Small", deserializedProductShort.Sizes[0]); + Assert.AreEqual("Medium", deserializedProductShort.Sizes[1]); + Assert.AreEqual("Large", deserializedProductShort.Sizes[2]); + } + + [Test] + public void MissingMemberIgnoreComplexValue() + { + JsonSerializer serializer = new JsonSerializer { MissingMemberHandling = MissingMemberHandling.Ignore }; + serializer.Converters.Add(new JavaScriptDateTimeConverter()); + + string response = @"{""PreProperty"":1,""DateProperty"":new Date(1225962698973),""PostProperty"":2}"; + + MyClass myClass = (MyClass)serializer.Deserialize(new StringReader(response), typeof(MyClass)); + + Assert.AreEqual(1, myClass.PreProperty); + Assert.AreEqual(2, myClass.PostProperty); + } + + [Test] + [ExpectedException(typeof(JsonSerializationException), ExpectedMessage = "Could not find member 'Missing' on object of type 'DoubleClass'")] + public void MissingMemeber() + { + string json = @"{""Missing"":1}"; + + JsonConvert.DeserializeObject(json, new JsonSerializerSettings { MissingMemberHandling = MissingMemberHandling.Error }); + } + + [Test] + public void MissingJson() + { + string json = @"{}"; + + JsonConvert.DeserializeObject(json, new JsonSerializerSettings + { + MissingMemberHandling = MissingMemberHandling.Error + }); + } + } +} \ No newline at end of file diff --git a/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs b/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs index fa7ea463..0d03ef31 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs @@ -673,8 +673,8 @@ namespace Newtonsoft.Json.Serialization if (!reader.Read()) throw new JsonSerializationException("Unexpected end when setting {0}'s value.".FormatWith(CultureInfo.InvariantCulture, memberName)); - if (reader.TokenType != JsonToken.Null) - SetRequiredProperty(memberName, requiredProperties); + // set required property even if null (matches WCF IsRequired behavour) + SetRequiredProperty(memberName, requiredProperties); try { @@ -734,6 +734,7 @@ namespace Newtonsoft.Json.Serialization } } +#if !PocketPC && !SILVERLIGHT && !NET20 private void HandleError(JsonReader reader, int initialDepth) { ClearErrorContext(); @@ -743,5 +744,6 @@ namespace Newtonsoft.Json.Serialization reader.Read(); } } +#endif } } \ No newline at end of file diff --git a/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs b/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs index a03c7556..d3e92b05 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs @@ -490,6 +490,7 @@ namespace Newtonsoft.Json.Serialization contract.InvokeOnSerialized(values); } +#if !PocketPC && !SILVERLIGHT && !NET20 private void HandleError(JsonWriter writer, int initialDepth) { ClearErrorContext(); @@ -499,5 +500,6 @@ namespace Newtonsoft.Json.Serialization writer.WriteEnd(); } } +#endif } } \ No newline at end of file