-Fixed serializing protected override properties

This commit is contained in:
James Newton-King
2016-11-27 13:33:52 +13:00
parent 38809c68e8
commit 5269ce81c0
2 changed files with 75 additions and 38 deletions
@@ -552,8 +552,8 @@ namespace Newtonsoft.Json.Tests.Serialization
public void IncompleteContainers()
{
ExceptionAssert.Throws<JsonSerializationException>(
() => JsonConvert.DeserializeObject<IList<object>>("[1,"),
"Unexpected end when deserializing array. Path '[0]', line 1, position 3.");
() => JsonConvert.DeserializeObject<IList<object>>("[1,"),
"Unexpected end when deserializing array. Path '[0]', line 1, position 3.");
ExceptionAssert.Throws<JsonSerializationException>(
() => JsonConvert.DeserializeObject<IList<int>>("[1,"),
@@ -1817,7 +1817,7 @@ namespace Newtonsoft.Json.Tests.Serialization
Assert.IsNotNull(deserialized.foo);
Assert.AreEqual("value", deserialized.foo.bar);
}
[Test]
public void ConversionOperator()
{
@@ -3273,7 +3273,10 @@ keyword such as type of business.""
testClass.co = new Co();
String strFromTest = JsonConvert.SerializeObject(testClass);
ExceptionAssert.Throws<JsonSerializationException>(() => { InterfacePropertyTestClass testFromDe = (InterfacePropertyTestClass)JsonConvert.DeserializeObject(strFromTest, typeof(InterfacePropertyTestClass)); }, @"Could not create an instance of type Newtonsoft.Json.Tests.TestObjects.ICo. Type is an interface or abstract class and cannot be instantiated. Path 'co.Name', line 1, position 14.");
ExceptionAssert.Throws<JsonSerializationException>(() =>
{
InterfacePropertyTestClass testFromDe = (InterfacePropertyTestClass)JsonConvert.DeserializeObject(strFromTest, typeof(InterfacePropertyTestClass));
}, @"Could not create an instance of type Newtonsoft.Json.Tests.TestObjects.ICo. Type is an interface or abstract class and cannot be instantiated. Path 'co.Name', line 1, position 14.");
}
private Person GetPerson()
@@ -7200,7 +7203,10 @@ Path '', line 1, position 1.");
null
]";
ExceptionAssert.Throws<JsonSerializationException>(() => { List<int> numbers = JsonConvert.DeserializeObject<List<int>>(json); }, "Error converting value {null} to type 'System.Int32'. Path '[3]', line 5, position 6.");
ExceptionAssert.Throws<JsonSerializationException>(() =>
{
List<int> numbers = JsonConvert.DeserializeObject<List<int>>(json);
}, "Error converting value {null} to type 'System.Int32'. Path '[3]', line 5, position 6.");
}
#if !(PORTABLE)
@@ -8229,7 +8235,7 @@ Path '', line 1, position 1.");
KeyValuePair<int, string> result =
JsonConvert.DeserializeObject<KeyValuePair<int, string>>(
"{key: 123, \"VALUE\": \"test value\"}"
);
);
Assert.AreEqual(123, result.Key);
Assert.AreEqual("test value", result.Value);
@@ -8950,7 +8956,7 @@ Path '', line 1, position 1.");
{
string json = JsonConvert.SerializeObject(
new Dictionary<Size, Size> { { new Size(1, 2), new Size(3, 4) } }
);
);
Assert.AreEqual(@"{""1, 2"":""3, 4""}", json);
@@ -9678,13 +9684,13 @@ Path '', line 1, position 1.");
}";
ExceptionAssert.Throws<JsonSerializationException>(() =>
{
JsonConvert.DeserializeObject<System.Net.Mail.MailMessage>(
JsonMessage,
new MailAddressReadConverter(),
new AttachmentReadConverter(),
new EncodingReadConverter());
},
{
JsonConvert.DeserializeObject<System.Net.Mail.MailMessage>(
JsonMessage,
new MailAddressReadConverter(),
new AttachmentReadConverter(),
new EncodingReadConverter());
},
"Cannot populate list type System.Net.Mime.HeaderCollection. Path 'Headers', line 26, position 14.");
}
@@ -9789,6 +9795,33 @@ Path '', line 1, position 1.");
ExceptionAssert.Throws<JsonSerializationException>(() => JsonConvert.DeserializeObject<CompletionDataRequest>(s), "Unexpected end when deserializing object. Path 'dataSource', line 1, position 63.");
}
[Test]
public void ChildClassWithProtectedOverridePlusJsonProperty_Serialize()
{
var propertyValue = "test";
var testJson = @"{ 'MyProperty' : '" + propertyValue + "' }";
var testObject = JsonConvert.DeserializeObject<ChildClassWithProtectedOverridePlusJsonProperty>(testJson);
Assert.AreEqual(propertyValue, testObject.GetPropertyValue(), "MyProperty should be populated");
}
}
public class BaseClassWithProtectedVirtual
{
protected virtual string MyProperty { get; set; }
}
public class ChildClassWithProtectedOverridePlusJsonProperty : BaseClassWithProtectedVirtual
{
[JsonProperty]
protected override string MyProperty { get; set; }
public string GetPropertyValue()
{
return MyProperty;
}
}
public class DerivedWithPrivate : BaseWithPrivate
@@ -98,13 +98,13 @@ namespace Newtonsoft.Json.Utilities
{
ValidationUtils.ArgumentNotNull(propertyInfo, nameof(propertyInfo));
MethodInfo m = propertyInfo.GetGetMethod();
MethodInfo m = propertyInfo.GetGetMethod(true);
if (m != null && m.IsVirtual)
{
return true;
}
m = propertyInfo.GetSetMethod();
m = propertyInfo.GetSetMethod(true);
if (m != null && m.IsVirtual)
{
return true;
@@ -1017,31 +1017,31 @@ namespace Newtonsoft.Json.Utilities
{
PropertyInfo subTypeProperty = propertyInfo;
if (!IsPublic(subTypeProperty))
if (!subTypeProperty.IsVirtual())
{
// have to test on name rather than reference because instances are different
// depending on the type that GetProperties was called on
int index = initialProperties.IndexOf(p => p.Name == subTypeProperty.Name);
if (index == -1)
if (!IsPublic(subTypeProperty))
{
initialProperties.Add(subTypeProperty);
}
else
{
PropertyInfo childProperty = initialProperties[index];
// don't replace public child with private base
if (!IsPublic(childProperty))
// have to test on name rather than reference because instances are different
// depending on the type that GetProperties was called on
int index = initialProperties.IndexOf(p => p.Name == subTypeProperty.Name);
if (index == -1)
{
// replace nonpublic properties for a child, but gotten from
// the parent with the one from the child
// the property gotten from the child will have access to private getter/setter
initialProperties[index] = subTypeProperty;
initialProperties.Add(subTypeProperty);
}
else
{
PropertyInfo childProperty = initialProperties[index];
// don't replace public child with private base
if (!IsPublic(childProperty))
{
// replace nonpublic properties for a child, but gotten from
// the parent with the one from the child
// the property gotten from the child will have access to private getter/setter
initialProperties[index] = subTypeProperty;
}
}
}
}
else
{
if (!subTypeProperty.IsVirtual())
else
{
int index = initialProperties.IndexOf(p => p.Name == subTypeProperty.Name
&& p.DeclaringType == subTypeProperty.DeclaringType);
@@ -1051,12 +1051,16 @@ namespace Newtonsoft.Json.Utilities
initialProperties.Add(subTypeProperty);
}
}
else
}
else
{
MethodInfo subTypePropertyBaseDefinition = subTypeProperty.GetBaseDefinition();
if (subTypePropertyBaseDefinition != null)
{
int index = initialProperties.IndexOf(p => p.Name == subTypeProperty.Name
&& p.IsVirtual()
&& p.GetBaseDefinition() != null
&& p.GetBaseDefinition().DeclaringType.IsAssignableFrom(subTypeProperty.GetBaseDefinition().DeclaringType));
&& p.GetBaseDefinition().DeclaringType.IsAssignableFrom(subTypePropertyBaseDefinition.DeclaringType));
if (index == -1)
{