From da491c3a0f246a240fe75f98d4d94e97e15a4441 Mon Sep 17 00:00:00 2001 From: James Newton-King Date: Wed, 1 May 2013 20:26:05 +1200 Subject: [PATCH] -Added NullValueHandling and DefaultValueHandling support to serializing dynamic properties --- .../Serialization/DynamicTests.cs | 72 +++++++++++++++++++ .../JsonSerializerInternalWriter.cs | 15 ++++ 2 files changed, 87 insertions(+) diff --git a/Src/Newtonsoft.Json.Tests/Serialization/DynamicTests.cs b/Src/Newtonsoft.Json.Tests/Serialization/DynamicTests.cs index c90b5a01..50c74494 100644 --- a/Src/Newtonsoft.Json.Tests/Serialization/DynamicTests.cs +++ b/Src/Newtonsoft.Json.Tests/Serialization/DynamicTests.cs @@ -250,6 +250,78 @@ namespace Newtonsoft.Json.Tests.Serialization Assert.AreEqual(false, foo.Values["retweeted"]); } + + [Test] + public void SerializeDynamicObjectWithNullValueHandlingIgnore() + { + dynamic o = new TestDynamicObject(); + o.Text = "Text!"; + o.Int = int.MaxValue; + o.ChildObject = null; // Tests an explicitly defined property of a dynamic object with a null value. + o.DynamicChildObject = null; // vs. a completely dynamic defined property. + + string json = JsonConvert.SerializeObject(o, Formatting.Indented, new JsonSerializerSettings + { + NullValueHandling = NullValueHandling.Ignore, + }); + + Console.WriteLine(json); + + Assert.AreEqual(@"{ + ""Explicit"": false, + ""Text"": ""Text!"", + ""Int"": 2147483647 +}", json); + } + + [Test] + public void SerializeDynamicObjectWithNullValueHandlingInclude() + { + dynamic o = new TestDynamicObject(); + o.Text = "Text!"; + o.Int = int.MaxValue; + o.ChildObject = null; // Tests an explicitly defined property of a dynamic object with a null value. + o.DynamicChildObject = null; // vs. a completely dynamic defined property. + + string json = JsonConvert.SerializeObject(o, Formatting.Indented, new JsonSerializerSettings + { + NullValueHandling = NullValueHandling.Include, + }); + + Console.WriteLine(json); + + Assert.AreEqual(@"{ + ""Explicit"": false, + ""Text"": ""Text!"", + ""DynamicChildObject"": null, + ""Int"": 2147483647, + ""ChildObject"": null +}", json); + } + + [Test] + public void SerializeDynamicObjectWithDefaultValueHandlingIgnore() + { + dynamic o = new TestDynamicObject(); + o.Text = "Text!"; + o.Int = int.MaxValue; + o.IntDefault = 0; + o.NUllableIntDefault = default(int?); + o.ChildObject = null; // Tests an explicitly defined property of a dynamic object with a null value. + o.DynamicChildObject = null; // vs. a completely dynamic defined property. + + string json = JsonConvert.SerializeObject(o, Formatting.Indented, new JsonSerializerSettings + { + DefaultValueHandling = DefaultValueHandling.Ignore, + }); + + Console.WriteLine(json); + + Assert.AreEqual(@"{ + ""Text"": ""Text!"", + ""Int"": 2147483647 +}", json); + } } public class DynamicChildObject diff --git a/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs b/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs index 7e67c1fd..8b226912 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs @@ -757,6 +757,9 @@ To fix this error either change the environment to be fully trusted, change the { JsonContract valueContract = GetContractSafe(memberValue); + if (!ShouldWriteDynamicProperty(memberValue)) + continue; + if (CheckForCircularReference(writer, memberValue, null, valueContract, contract, member)) { string resolvedPropertyName = (contract.PropertyNameResolver != null) @@ -784,6 +787,18 @@ To fix this error either change the environment to be fully trusted, change the } #endif + private bool ShouldWriteDynamicProperty(object memberValue) + { + if (Serializer._nullValueHandling == NullValueHandling.Ignore && memberValue == null) + return false; + + if (HasFlag(Serializer._defaultValueHandling, DefaultValueHandling.Ignore) && + (memberValue == null || MiscellaneousUtils.ValueEquals(memberValue, ReflectionUtils.GetDefaultValue(memberValue.GetType())))) + return false; + + return true; + } + private bool ShouldWriteType(TypeNameHandling typeNameHandlingFlag, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty) { TypeNameHandling resolvedTypeNameHandling =