diff --git a/Src/Newtonsoft.Json.Tests/Serialization/NullValueHandlingTests.cs b/Src/Newtonsoft.Json.Tests/Serialization/NullValueHandlingTests.cs index 18eb4ea4..d1e884b3 100644 --- a/Src/Newtonsoft.Json.Tests/Serialization/NullValueHandlingTests.cs +++ b/Src/Newtonsoft.Json.Tests/Serialization/NullValueHandlingTests.cs @@ -40,6 +40,20 @@ namespace Newtonsoft.Json.Tests.Serialization [TestFixture] public class NullValueHandlingTests : TestFixtureBase { + private const string MovieNullValueHandlingIncludeExpectedResult = @"{ + ""Name"": ""Bad Boys III"", + ""Description"": ""It's no Bad Boys"", + ""Classification"": null, + ""Studio"": null, + ""ReleaseDate"": null, + ""ReleaseCountries"": null +}"; + + private const string MovieNullValueHandlingIgnoreExpectedResult = @"{ + ""Name"": ""Bad Boys III"", + ""Description"": ""It's no Bad Boys"" +}"; + #if !NET20 [Test] public void DeserializeNullIntoDateTime() @@ -110,19 +124,55 @@ namespace Newtonsoft.Json.Tests.Serialization // "Description": "It's no Bad Boys" // } - StringAssert.AreEqual(@"{ - ""Name"": ""Bad Boys III"", - ""Description"": ""It's no Bad Boys"", - ""Classification"": null, - ""Studio"": null, - ""ReleaseDate"": null, - ""ReleaseCountries"": null -}", included); + StringAssert.AreEqual(MovieNullValueHandlingIncludeExpectedResult, included); - StringAssert.AreEqual(@"{ - ""Name"": ""Bad Boys III"", - ""Description"": ""It's no Bad Boys"" -}", ignored); + StringAssert.AreEqual(MovieNullValueHandlingIgnoreExpectedResult, ignored); + } + + [Test] + public void JsonObjectNullValueHandlingIgnore() + { + var movie = new MovieWithJsonObjectNullValueHandlingIgnore + { + Name = "Bad Boys III", + Description = "It's no Bad Boys" + }; + + string ignored = JsonConvert.SerializeObject(movie, + Formatting.Indented, + new JsonSerializerSettings { NullValueHandling = NullValueHandling.Include }); + + // { + // "Name": "Bad Boys III", + // "Description": "It's no Bad Boys" + // } + + StringAssert.AreEqual(MovieNullValueHandlingIgnoreExpectedResult, ignored); + } + + [Test] + public void JsonObjectNullValueHandlingInclude() + { + var movie = new MovieWithJsonObjectNullValueHandlingInclude + { + Name = "Bad Boys III", + Description = "It's no Bad Boys" + }; + + string included = JsonConvert.SerializeObject(movie, + Formatting.Indented, + new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore }); + + // { + // "Name": "Bad Boys III", + // "Description": "It's no Bad Boys", + // "Classification": null, + // "Studio": null, + // "ReleaseDate": null, + // "ReleaseCountries": null + // } + + StringAssert.AreEqual(MovieNullValueHandlingIncludeExpectedResult, included); } } } \ No newline at end of file diff --git a/Src/Newtonsoft.Json.Tests/TestObjects/MovieWithJsonObjectNullValueHandlingIgnore.cs b/Src/Newtonsoft.Json.Tests/TestObjects/MovieWithJsonObjectNullValueHandlingIgnore.cs new file mode 100644 index 00000000..6efc2ebc --- /dev/null +++ b/Src/Newtonsoft.Json.Tests/TestObjects/MovieWithJsonObjectNullValueHandlingIgnore.cs @@ -0,0 +1,41 @@ +#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.Collections.Generic; + +namespace Newtonsoft.Json.Tests.TestObjects +{ + [JsonObject(ItemNullValueHandling = NullValueHandling.Ignore)] + public class MovieWithJsonObjectNullValueHandlingIgnore + { + public string Name { get; set; } + public string Description { get; set; } + public string Classification { get; set; } + public string Studio { get; set; } + public DateTime? ReleaseDate { get; set; } + public List ReleaseCountries { get; set; } + } +} \ No newline at end of file diff --git a/Src/Newtonsoft.Json.Tests/TestObjects/MovieWithJsonObjectNullValueHandlingInclude.cs b/Src/Newtonsoft.Json.Tests/TestObjects/MovieWithJsonObjectNullValueHandlingInclude.cs new file mode 100644 index 00000000..1a1acdb6 --- /dev/null +++ b/Src/Newtonsoft.Json.Tests/TestObjects/MovieWithJsonObjectNullValueHandlingInclude.cs @@ -0,0 +1,41 @@ +#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.Collections.Generic; + +namespace Newtonsoft.Json.Tests.TestObjects +{ + [JsonObject(ItemNullValueHandling = NullValueHandling.Include)] + public class MovieWithJsonObjectNullValueHandlingInclude + { + public string Name { get; set; } + public string Description { get; set; } + public string Classification { get; set; } + public string Studio { get; set; } + public DateTime? ReleaseDate { get; set; } + public List ReleaseCountries { get; set; } + } +} \ No newline at end of file diff --git a/Src/Newtonsoft.Json/JsonObjectAttribute.cs b/Src/Newtonsoft.Json/JsonObjectAttribute.cs index 5f824993..0b532f29 100644 --- a/Src/Newtonsoft.Json/JsonObjectAttribute.cs +++ b/Src/Newtonsoft.Json/JsonObjectAttribute.cs @@ -34,10 +34,11 @@ namespace Newtonsoft.Json public sealed class JsonObjectAttribute : JsonContainerAttribute { private MemberSerialization _memberSerialization = MemberSerialization.OptOut; - + // yuck. can't set nullable properties on an attribute in C# // have to use this approach to get an unset default state internal Required? _itemRequired; + internal NullValueHandling? _itemNullValueHandling; /// /// Gets or sets the member serialization. @@ -49,6 +50,16 @@ namespace Newtonsoft.Json set => _memberSerialization = value; } + /// + /// Gets or sets the null value handling. + /// + /// The null value handling. + public NullValueHandling ItemNullValueHandling + { + get => _itemNullValueHandling ?? default(NullValueHandling); + set => _itemNullValueHandling = value; + } + /// /// Gets or sets a value that indicates whether the object's properties are required. /// diff --git a/Src/Newtonsoft.Json/Serialization/DefaultContractResolver.cs b/Src/Newtonsoft.Json/Serialization/DefaultContractResolver.cs index ff2708ae..44858f72 100644 --- a/Src/Newtonsoft.Json/Serialization/DefaultContractResolver.cs +++ b/Src/Newtonsoft.Json/Serialization/DefaultContractResolver.cs @@ -1509,6 +1509,11 @@ namespace Newtonsoft.Json.Serialization #endif } + if (property.NullValueHandling == null && containerAttribute is JsonObjectAttribute objectAttribute) + { + property.NullValueHandling = objectAttribute._itemNullValueHandling; + } + if (requiredAttribute != null) { property._required = Required.Always;