From 2941344044b1340d982a5f7c5edfd2b8882f7840 Mon Sep 17 00:00:00 2001 From: JamesNK Date: Mon, 16 Jan 2012 08:00:48 +0000 Subject: [PATCH] -Fixed serializing types with hidden properties --- .../Serialization/JsonSerializerTest.cs | 27 ++++++++++++++++++ .../Serialization/DefaultContractResolver.cs | 1 + .../Serialization/JsonProperty.cs | 6 ++++ .../Serialization/JsonPropertyCollection.cs | 28 +++++++++++++++---- 4 files changed, 57 insertions(+), 5 deletions(-) diff --git a/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs b/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs index 14df3b61..7d5d7386 100644 --- a/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs +++ b/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs @@ -5112,6 +5112,23 @@ keyword such as type of business."" Assert.AreEqual(d1.Count, d2.Count); Assert.AreEqual(d1[0], d2[0]); } + + [Test] + public void SerializeInheritanceHierarchyWithDuplicateProperty() + { + Bb b = new Bb(); + b.no = true; + Aa a = b; + a.no = int.MaxValue; + + string json = JsonConvert.SerializeObject(b); + + Assert.AreEqual(@"{""no"":true}", json); + + Bb b2 = JsonConvert.DeserializeObject(json); + + Assert.AreEqual(true, b2.no); + } } public class DecimalTestClass @@ -5146,6 +5163,16 @@ keyword such as type of business."" public Uri Uri { get; set; } } + class Aa + { + public int no; + } + + class Bb : Aa + { + public bool no; + } + #if !(NET35 || NET20 || SILVERLIGHT || WINDOWS_PHONE) [JsonObject(MemberSerialization.OptIn)] public class GameObject diff --git a/Src/Newtonsoft.Json/Serialization/DefaultContractResolver.cs b/Src/Newtonsoft.Json/Serialization/DefaultContractResolver.cs index 75050339..b3a5fb27 100644 --- a/Src/Newtonsoft.Json/Serialization/DefaultContractResolver.cs +++ b/Src/Newtonsoft.Json/Serialization/DefaultContractResolver.cs @@ -808,6 +808,7 @@ namespace Newtonsoft.Json.Serialization { JsonProperty property = new JsonProperty(); property.PropertyType = ReflectionUtils.GetMemberUnderlyingType(member); + property.DeclaringType = member.DeclaringType; property.ValueProvider = CreateMemberValueProvider(member); bool allowNonPublicAccess; diff --git a/Src/Newtonsoft.Json/Serialization/JsonProperty.cs b/Src/Newtonsoft.Json/Serialization/JsonProperty.cs index e0d055b7..f2240eca 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonProperty.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonProperty.cs @@ -41,6 +41,12 @@ namespace Newtonsoft.Json.Serialization /// The name of the property. public string PropertyName { get; set; } + /// + /// Gets or sets the type that declared this property. + /// + /// The type that declared this property. + public Type DeclaringType { get; set; } + /// /// Gets or sets the order of serialization and deserialization of a member. /// diff --git a/Src/Newtonsoft.Json/Serialization/JsonPropertyCollection.cs b/Src/Newtonsoft.Json/Serialization/JsonPropertyCollection.cs index 5c2d525e..62746593 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonPropertyCollection.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonPropertyCollection.cs @@ -73,12 +73,30 @@ namespace Newtonsoft.Json.Serialization JsonProperty existingProperty = this[property.PropertyName]; - if (!existingProperty.Ignored) - throw new JsonSerializationException( - "A member with the name '{0}' already exists on '{1}'. Use the JsonPropertyAttribute to specify another name.".FormatWith(CultureInfo.InvariantCulture, property.PropertyName, _type)); + if (existingProperty.Ignored) + { + // remove ignored property so it can be replaced in collection + Remove(existingProperty); + return; + } - // remove ignored property so it can be replaced in collection - Remove(existingProperty); + if (property.DeclaringType != null && existingProperty.DeclaringType != null) + { + if (property.DeclaringType.IsSubclassOf(existingProperty.DeclaringType)) + { + // current property is on a derived class and hides the existing + Remove(existingProperty); + return; + } + if (existingProperty.DeclaringType.IsSubclassOf(property.DeclaringType)) + { + // current property is hidden by the existing so don't add it + return; + } + } + + throw new JsonSerializationException( + "A member with the name '{0}' already exists on '{1}'. Use the JsonPropertyAttribute to specify another name.".FormatWith(CultureInfo.InvariantCulture, property.PropertyName, _type)); } Add(property);