-Fixed using extension data with a non-default constructor

This commit is contained in:
James Newton-King
2013-12-29 19:45:41 +13:00
parent cc730cc860
commit 6562d9d31c
4 changed files with 103 additions and 9 deletions
@@ -604,6 +604,19 @@ namespace Newtonsoft.Json.Tests.Serialization
public IDictionary<object, object> ExtensionData;
}
public class PublicExtensionDataAttributeTestClassWithNonDefaultConstructor
{
public string Name { get; set; }
public PublicExtensionDataAttributeTestClassWithNonDefaultConstructor(string name)
{
Name = name;
}
[JsonExtensionData]
public IDictionary<object, object> ExtensionData;
}
public class PublicNoReadExtensionDataAttributeTestClass
{
public string Name { get; set; }
@@ -785,6 +798,34 @@ namespace Newtonsoft.Json.Tests.Serialization
Assert.AreEqual(2m, bizzaroC2.HourlyWage);
}
[Test]
public void DeserializePublicExtensionDataTypeNamdHandlingNonDefaultConstructor()
{
string json = @"{
""$id"": ""1"",
""Name"": ""Name!"",
""Test"": 1,
""Self"": {
""$type"": ""Newtonsoft.Json.Tests.TestObjects.WagePerson, Newtonsoft.Json.Tests"",
""HourlyWage"": 2.0,
""Name"": null,
""BirthDate"": ""0001-01-01T00:00:00"",
""LastModified"": ""0001-01-01T00:00:00""
}
}";
PublicExtensionDataAttributeTestClassWithNonDefaultConstructor c2 = JsonConvert.DeserializeObject<PublicExtensionDataAttributeTestClassWithNonDefaultConstructor>(json, new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.Objects
});
Assert.AreEqual("Name!", c2.Name);
WagePerson bizzaroC2 = (WagePerson)c2.ExtensionData["Self"];
Assert.AreEqual(2m, bizzaroC2.HourlyWage);
}
[Test]
public void SerializePublicExtensionDataTypeNamdHandling()
{
@@ -8715,6 +8756,43 @@ Parameter name: value",
Assert.AreEqual("EventName!", values2[0][0, 0].EventName);
}
public class ExtensionDataDeserializeWithNonDefaultConstructor
{
public ExtensionDataDeserializeWithNonDefaultConstructor(string name)
{
Name = name;
}
[JsonExtensionData]
public IDictionary<string, JToken> _extensionData;
public string Name { get; set; }
}
[Test]
public void ExtensionDataDeserializeWithNonDefaultConstructorTest()
{
ExtensionDataDeserializeWithNonDefaultConstructor c = new ExtensionDataDeserializeWithNonDefaultConstructor("Name!");
c._extensionData = new Dictionary<string, JToken>
{
{"Key!", "Value!"}
};
string json = JsonConvert.SerializeObject(c, Formatting.Indented);
Assert.AreEqual(@"{
""Name"": ""Name!"",
""Key!"": ""Value!""
}", json);
var c2 = JsonConvert.DeserializeObject<ExtensionDataDeserializeWithNonDefaultConstructor>(json);
Assert.AreEqual("Name!", c2.Name);
Assert.IsNotNull(c2._extensionData);
Assert.AreEqual(1, c2._extensionData.Count);
Assert.AreEqual("Value!", (string)c2._extensionData["Key!"]);
}
#if NETFX_CORE
[Test]
public void SerializeWinRTJsonObject()
+1 -1
View File
@@ -178,7 +178,7 @@ namespace Newtonsoft.Json.Tests
{
try
{
action();
; action();
Assert.Fail("Exception of type {0} expected; got none exception", typeof(TException).Name);
}
@@ -75,7 +75,7 @@ namespace Newtonsoft.Json.Serialization
if (!ReflectionUtils.IsNullable(ReflectionUtils.GetMemberUnderlyingType(_memberInfo)))
throw new JsonSerializationException("Incompatible value. Cannot set {0} to null.".FormatWith(CultureInfo.InvariantCulture, _memberInfo));
}
else if (!ReflectionUtils.GetMemberUnderlyingType(_memberInfo).IsAssignableFrom(value.GetType()))
else if (!ReflectionUtils.GetMemberUnderlyingType(_memberInfo).IsInstanceOfType(value))
{
throw new JsonSerializationException("Incompatible value. Cannot set {0} to type {1}.".FormatWith(CultureInfo.InvariantCulture, _memberInfo, value.GetType()));
}
@@ -1458,7 +1458,8 @@ To fix this error either change the environment to be fully trusted, change the
if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info)
TraceWriter.Trace(TraceLevel.Info, JsonPosition.FormatMessage(reader as IJsonLineInfo, reader.Path, "Deserializing {0} using a non-default constructor '{1}'.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType, constructorInfo)), null);
IDictionary<JsonProperty, object> propertyValues = ResolvePropertyAndConstructorValues(contract, containerProperty, reader, objectType);
IDictionary<string, object> extensionData;
IDictionary<JsonProperty, object> propertyValues = ResolvePropertyAndConstructorValues(contract, containerProperty, reader, objectType, out extensionData);
IDictionary<ParameterInfo, object> constructorParameters = constructorInfo.GetParameters().ToDictionary(p => p, p => (object)null);
IDictionary<JsonProperty, object> remainingPropertyValues = new Dictionary<JsonProperty, object>();
@@ -1493,7 +1494,7 @@ To fix this error either change the environment to be fully trusted, change the
JsonProperty property = remainingPropertyValue.Key;
object value = remainingPropertyValue.Value;
if (ShouldSetPropertyValue(remainingPropertyValue.Key, remainingPropertyValue.Value))
if (ShouldSetPropertyValue(property, value))
{
property.ValueProvider.SetValue(createdObject, value);
}
@@ -1537,6 +1538,14 @@ To fix this error either change the environment to be fully trusted, change the
}
}
if (extensionData != null)
{
foreach (KeyValuePair<string, object> e in extensionData)
{
contract.ExtensionDataSetter(createdObject, e.Key, e.Value);
}
}
EndObject(createdObject, reader, contract, reader.Depth, propertiesPresence);
OnDeserialized(reader, contract, createdObject);
@@ -1556,8 +1565,10 @@ To fix this error either change the environment to be fully trusted, change the
return value;
}
private IDictionary<JsonProperty, object> ResolvePropertyAndConstructorValues(JsonObjectContract contract, JsonProperty containerProperty, JsonReader reader, Type objectType)
private IDictionary<JsonProperty, object> ResolvePropertyAndConstructorValues(JsonObjectContract contract, JsonProperty containerProperty, JsonReader reader, Type objectType, out IDictionary<string, object> extensionData)
{
extensionData = (contract.ExtensionDataSetter != null) ? new Dictionary<string, object>() : null;
IDictionary<JsonProperty, object> propertyValues = new Dictionary<JsonProperty, object>();
bool exit = false;
do
@@ -1594,10 +1605,7 @@ To fix this error either change the environment to be fully trusted, change the
propertyValue = CreateValueInternal(reader, property.PropertyType, property.PropertyContract, property, contract, containerProperty, null);
propertyValues[property] = propertyValue;
}
else
{
reader.Skip();
continue;
}
}
else
@@ -1610,7 +1618,15 @@ To fix this error either change the environment to be fully trusted, change the
if (Serializer._missingMemberHandling == MissingMemberHandling.Error)
throw JsonSerializationException.Create(reader, "Could not find member '{0}' on object of type '{1}'".FormatWith(CultureInfo.InvariantCulture, memberName, objectType.Name));
}
if (extensionData != null)
{
object value = CreateValueInternal(reader, null, null, null, contract, containerProperty, null);
extensionData[memberName] = value;
}
else
{
reader.Skip();
}
break;