From f4e8c3d2cad5402ff2de73964052178effa55406 Mon Sep 17 00:00:00 2001 From: James Newton-King Date: Sun, 17 May 2015 22:48:55 +1200 Subject: [PATCH] -Fixed serializing root references from JsonConverters --- .../PreserveReferencesHandlingTests.cs | 95 +++++++++++++++++++ .../JsonSerializerInternalWriter.cs | 9 +- 2 files changed, 103 insertions(+), 1 deletion(-) diff --git a/Src/Newtonsoft.Json.Tests/Serialization/PreserveReferencesHandlingTests.cs b/Src/Newtonsoft.Json.Tests/Serialization/PreserveReferencesHandlingTests.cs index f0fb9255..1c469eb1 100644 --- a/Src/Newtonsoft.Json.Tests/Serialization/PreserveReferencesHandlingTests.cs +++ b/Src/Newtonsoft.Json.Tests/Serialization/PreserveReferencesHandlingTests.cs @@ -47,6 +47,101 @@ namespace Newtonsoft.Json.Tests.Serialization [TestFixture] public class PreserveReferencesHandlingTests : TestFixtureBase { + public class ContentB + { + public bool SomeValue { get; set; } + } + + [JsonConverter(typeof(ListConverter))] + public class ContentA : List + { + public ContentB B { get; set; } + + public ContentA() + { + B = new ContentB(); + } + } + + public class ListConverter : JsonConverter + { + public override bool CanConvert(Type objectType) + { + return true; + } + + public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) + { + return new ContentA() { B = serializer.Deserialize(reader) }; // Construct my data back. + } + + public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) + { + ContentB b = ((ContentA)value).B; + serializer.Serialize(writer, b); // My Content.B contains all useful data. + } + } + + public class Container + { + public List ListA { get; set; } + public List ListB { get; set; } + + public Container() + { + ListA = new List(); + ListB = new List(); + } + } + + [Test] + public void SerializeReferenceInConvert() + { + JsonSerializerSettings settings = new JsonSerializerSettings(); + settings.PreserveReferencesHandling = PreserveReferencesHandling.All; + settings.TypeNameHandling = TypeNameHandling.All; + settings.Formatting = Formatting.Indented; + + Container c1 = new Container(); + ContentA content = new ContentA(); + content.B.SomeValue = true; + c1.ListA.Add(content); + c1.ListB.Add(content); + + string s = JsonConvert.SerializeObject(c1, settings); + + StringAssert.AreEqual(@"{ + ""$id"": ""1"", + ""$type"": ""Newtonsoft.Json.Tests.Serialization.PreserveReferencesHandlingTests+Container, Newtonsoft.Json.Tests"", + ""ListA"": { + ""$id"": ""2"", + ""$type"": ""System.Collections.Generic.List`1[[Newtonsoft.Json.Tests.Serialization.PreserveReferencesHandlingTests+ContentA, Newtonsoft.Json.Tests]], mscorlib"", + ""$values"": [ + { + ""$id"": ""3"", + ""$type"": ""Newtonsoft.Json.Tests.Serialization.PreserveReferencesHandlingTests+ContentB, Newtonsoft.Json.Tests"", + ""SomeValue"": true + } + ] + }, + ""ListB"": { + ""$id"": ""4"", + ""$type"": ""System.Collections.Generic.List`1[[Newtonsoft.Json.Tests.Serialization.PreserveReferencesHandlingTests+ContentA, Newtonsoft.Json.Tests]], mscorlib"", + ""$values"": [ + { + ""$ref"": ""3"" + } + ] + } +}", s); + + Container c2 = JsonConvert.DeserializeObject(s, settings); + + Assert.AreEqual(c2.ListA[0], c2.ListB[0]); + Assert.AreEqual(true, c2.ListA[0].B.SomeValue); + } + + public class Parent { public Child ReadOnlyChild diff --git a/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs b/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs index 743a18df..f3f9f6ae 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs @@ -70,7 +70,14 @@ namespace Newtonsoft.Json.Serialization try { - SerializeValue(jsonWriter, value, contract, null, null, null); + if (ShouldWriteReference(value, null, contract, null, null)) + { + WriteReference(jsonWriter, value); + } + else + { + SerializeValue(jsonWriter, value, contract, null, null, null); + } } catch (Exception ex) {