diff --git a/Src/Newtonsoft.Json.TestConsole/Properties/AssemblyInfo.cs b/Src/Newtonsoft.Json.TestConsole/Properties/AssemblyInfo.cs index 9be3690c..aa32efb8 100644 --- a/Src/Newtonsoft.Json.TestConsole/Properties/AssemblyInfo.cs +++ b/Src/Newtonsoft.Json.TestConsole/Properties/AssemblyInfo.cs @@ -33,4 +33,4 @@ using System.Runtime.InteropServices; // by using the '*' as shown below: // [assembly: AssemblyVersion("6.0.0.0")] [assembly: AssemblyVersion("6.0.0.0")] -[assembly: AssemblyFileVersion("6.0.6.17905")] +[assembly: AssemblyFileVersion("6.0.6.17911")] diff --git a/Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.cs b/Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.cs index be30b977..b22f60d7 100644 --- a/Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.cs +++ b/Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.cs @@ -74,4 +74,4 @@ using System.Security; // by using the '*' as shown below: [assembly: AssemblyVersion("6.0.0.0")] -[assembly: AssemblyFileVersion("6.0.6.17905")] +[assembly: AssemblyFileVersion("6.0.6.17911")] diff --git a/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs b/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs index afcc9cff..f3ba31f1 100644 --- a/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs +++ b/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs @@ -700,16 +700,17 @@ namespace Newtonsoft.Json.Tests.Serialization Assert.AreEqual(ratio.Numerator, ratio2.Numerator); } - public class IDeserializationCallbackTestObject : ISerializable, IDeserializationCallback + public class PreserveReferencesCallbackTestObject : ISerializable { internal string _stringValue; internal int _intValue; internal PersonReference _person1; internal PersonReference _person2; internal PersonReference _person3; + internal PreserveReferencesCallbackTestObject _parent; internal SerializationInfo _serializationInfo; - public IDeserializationCallbackTestObject(string stringValue, int intValue, PersonReference p1, PersonReference p2, PersonReference p3) + public PreserveReferencesCallbackTestObject(string stringValue, int intValue, PersonReference p1, PersonReference p2, PersonReference p3) { _stringValue = stringValue; _intValue = intValue; @@ -718,7 +719,7 @@ namespace Newtonsoft.Json.Tests.Serialization _person3 = p3; } - protected IDeserializationCallbackTestObject(SerializationInfo info, StreamingContext context) + protected PreserveReferencesCallbackTestObject(SerializationInfo info, StreamingContext context) { _serializationInfo = info; } @@ -730,25 +731,28 @@ namespace Newtonsoft.Json.Tests.Serialization info.AddValue("person1", _person1, typeof(PersonReference)); info.AddValue("person2", _person2, typeof(PersonReference)); info.AddValue("person3", _person3, typeof(PersonReference)); + info.AddValue("parent", _parent, typeof(PreserveReferencesCallbackTestObject)); } - void IDeserializationCallback.OnDeserialization(object sender) + [OnDeserialized] + private void OnDeserializedMethod(StreamingContext context) { if (_serializationInfo == null) return; _stringValue = _serializationInfo.GetString("stringValue"); _intValue = _serializationInfo.GetInt32("intValue"); - _person1 = (PersonReference) _serializationInfo.GetValue("person1", typeof(PersonReference)); - _person2 = (PersonReference) _serializationInfo.GetValue("person2", typeof(PersonReference)); - _person3 = (PersonReference) _serializationInfo.GetValue("person3", typeof(PersonReference)); + _person1 = (PersonReference)_serializationInfo.GetValue("person1", typeof(PersonReference)); + _person2 = (PersonReference)_serializationInfo.GetValue("person2", typeof(PersonReference)); + _person3 = (PersonReference)_serializationInfo.GetValue("person3", typeof(PersonReference)); + _parent = (PreserveReferencesCallbackTestObject)_serializationInfo.GetValue("parent", typeof(PreserveReferencesCallbackTestObject)); _serializationInfo = null; } } [Test] - public void DeserializeIDeserializationCallback() + public void PreserveReferencesCallbackTest() { var p1 = new PersonReference { @@ -762,7 +766,8 @@ namespace Newtonsoft.Json.Tests.Serialization p1.Spouse = p2; p2.Spouse = p1; - var obj = new IDeserializationCallbackTestObject("string!", 42, p1, p2, p1); + var obj = new PreserveReferencesCallbackTestObject("string!", 42, p1, p2, p1); + obj._parent = obj; var settings = new JsonSerializerSettings { @@ -792,10 +797,13 @@ namespace Newtonsoft.Json.Tests.Serialization }, ""person3"": { ""$ref"": ""2"" + }, + ""parent"": { + ""$ref"": ""1"" } }"); - IDeserializationCallbackTestObject obj2 = JsonConvert.DeserializeObject(json); + PreserveReferencesCallbackTestObject obj2 = JsonConvert.DeserializeObject(json); Assert.AreEqual(obj._stringValue, obj2._stringValue); Assert.AreEqual(obj._intValue, obj2._intValue); @@ -804,6 +812,8 @@ namespace Newtonsoft.Json.Tests.Serialization Assert.AreEqual(obj._person3.Name, obj2._person3.Name); Assert.AreEqual(obj2._person1, obj2._person3); Assert.AreEqual(obj2._person1.Spouse, obj2._person2); + Assert.AreEqual(obj2._person2.Spouse, obj2._person1); + Assert.AreEqual(obj2._parent, obj2); } #endif @@ -4041,9 +4051,9 @@ Path '', line 1, position 1."); JsonTypeReflector.SetFullyTrusted(false); JsonConvert.DeserializeObject("{booleanValue:true}"); - }, @"Type 'Newtonsoft.Json.Tests.Serialization.JsonSerializerTest+ISerializableTestObject' implements ISerializable but cannot be deserialized using the ISerializable interface because the current application is not fully trusted and ISerializable can expose secure data. -To fix this error either change the environment to be fully trusted, change the application to not deserialize the type, add JsonObjectAttribute to the type or change the JsonSerializer setting ContractResolver to use a new DefaultContractResolver with IgnoreSerializableInterface set to true. -Path 'booleanValue', line 1, position 14."); + }, @"Type 'Newtonsoft.Json.Tests.Serialization.JsonSerializerTest+ISerializableTestObject' implements ISerializable but cannot be deserialized using the ISerializable interface because the current application is not fully trusted and ISerializable can expose secure data." + Environment.NewLine + + @"To fix this error either change the environment to be fully trusted, change the application to not deserialize the type, add JsonObjectAttribute to the type or change the JsonSerializer setting ContractResolver to use a new DefaultContractResolver with IgnoreSerializableInterface set to true." + Environment.NewLine + + @"Path 'booleanValue', line 1, position 14."); } finally { @@ -4062,8 +4072,9 @@ Path 'booleanValue', line 1, position 14."); ISerializableTestObject value = new ISerializableTestObject("string!", 0, default(DateTimeOffset), null); JsonConvert.SerializeObject(value); - }, @"Type 'Newtonsoft.Json.Tests.Serialization.JsonSerializerTest+ISerializableTestObject' implements ISerializable but cannot be serialized using the ISerializable interface because the current application is not fully trusted and ISerializable can expose secure data. -To fix this error either change the environment to be fully trusted, change the application to not deserialize the type, add JsonObjectAttribute to the type or change the JsonSerializer setting ContractResolver to use a new DefaultContractResolver with IgnoreSerializableInterface set to true. Path ''."); + }, @"Type 'Newtonsoft.Json.Tests.Serialization.JsonSerializerTest+ISerializableTestObject' implements ISerializable but cannot be serialized using the ISerializable interface because the current application is not fully trusted and ISerializable can expose secure data." + Environment.NewLine + + @"To fix this error either change the environment to be fully trusted, change the application to not deserialize the type, add JsonObjectAttribute to the type or change the JsonSerializer setting ContractResolver to use a new DefaultContractResolver with IgnoreSerializableInterface set to true." + Environment.NewLine + + @"Path ''."); } finally { diff --git a/Src/Newtonsoft.Json/Properties/AssemblyInfo.cs b/Src/Newtonsoft.Json/Properties/AssemblyInfo.cs index a857c14b..ae3623f9 100644 --- a/Src/Newtonsoft.Json/Properties/AssemblyInfo.cs +++ b/Src/Newtonsoft.Json/Properties/AssemblyInfo.cs @@ -91,5 +91,5 @@ using System.Security; // by using the '*' as shown below: [assembly: AssemblyVersion("6.0.0.0")] -[assembly: AssemblyFileVersion("6.0.6.17905")] +[assembly: AssemblyFileVersion("6.0.6.17911")] [assembly: CLSCompliant(true)] diff --git a/Src/Newtonsoft.Json/Serialization/JsonISerializableContract.cs b/Src/Newtonsoft.Json/Serialization/JsonISerializableContract.cs index dab49ea4..d69e5fb5 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonISerializableContract.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonISerializableContract.cs @@ -40,12 +40,6 @@ namespace Newtonsoft.Json.Serialization /// The ISerializable object constructor. public ObjectConstructor ISerializableCreator { get; set; } - /// - /// Gets whether the type implements IDeserializationCallback. - /// - /// True if the type implements IDeserialiationCallback, otherwise false. - public bool HasDeserializationCallback { get; private set; } - /// /// Initializes a new instance of the class. /// @@ -54,9 +48,7 @@ namespace Newtonsoft.Json.Serialization : base(underlyingType) { ContractType = JsonContractType.Serializable; - HasDeserializationCallback = typeof(IDeserializationCallback).IsAssignableFrom(underlyingType); } } } - #endif \ No newline at end of file diff --git a/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs b/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs index f4b78e0f..e90c7e4d 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs @@ -1493,14 +1493,6 @@ namespace Newtonsoft.Json.Serialization OnDeserializing(reader, contract, createdObject); OnDeserialized(reader, contract, createdObject); - // According to documentation this method is called after the entire object graph is deserialized, - // however doing this isn't compatible with the type of serialization model used by JSON. - // The creation of an object with $id would end up postponed, causing references to it in the object graph - // to fail. The .NET Framework shows that it's valid to call this on-demand before that point if another - // object depends on this one, which is what will be done here in every case. - if (contract.HasDeserializationCallback) - ((IDeserializationCallback) createdObject).OnDeserialization(null); - return createdObject; }