{"action":"created","issue":{"url":"https://api.github.com/repos/JamesNK/Newtonsoft.Json/issues/570","labels_url":"https://api.github.com/repos/JamesNK/Newtonsoft.Json/issues/570/labels{/name}","comments_url":"https://api.github.com/repos/JamesNK/Newtonsoft.Json/issues/570/comments","events_url":"https://api.github.com/repos/JamesNK/Newtonsoft.Json/issues/570/events","html_url":"https://github.com/JamesNK/Newtonsoft.Json/issues/570","id":77143807,"number":570,"title":"[bug] Serialize same instance with converter in two lists using reference and type name causes duplicated id","user":{"login":"CnSimonChan","id":1330321,"avatar_url":"https://avatars.githubusercontent.com/u/1330321?v=3","gravatar_id":"","url":"https://api.github.com/users/CnSimonChan","html_url":"https://github.com/CnSimonChan","followers_url":"https://api.github.com/users/CnSimonChan/followers","following_url":"https://api.github.com/users/CnSimonChan/following{/other_user}","gists_url":"https://api.github.com/users/CnSimonChan/gists{/gist_id}","starred_url":"https://api.github.com/users/CnSimonChan/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/CnSimonChan/subscriptions","organizations_url":"https://api.github.com/users/CnSimonChan/orgs","repos_url":"https://api.github.com/users/CnSimonChan/repos","events_url":"https://api.github.com/users/CnSimonChan/events{/privacy}","received_events_url":"https://api.github.com/users/CnSimonChan/received_events","type":"User","site_admin":false},"labels":[],"state":"closed","locked":false,"assignee":null,"milestone":null,"comments":2,"created_at":"2015-05-16T22:10:51Z","updated_at":"2015-05-17T18:57:07Z","closed_at":"2015-05-17T10:50:00Z","body":"I'm using 7.0.1b3 on .NET and 6.0.8 on Portable Library.\r\n\r\n````C#\r\n// I Want to serialize my complex data:\r\nclass ContentB { public bool SomeValue { get; set; } }\r\n\r\n[JsonConverter(typeof(ListConverter))]\r\nclass ContentA : List<object>\r\n{\r\n    public ContentB B { get; set; } = new ContentB();\r\n}\r\n\r\n// It's a List<object> so I need to serialize it with a converter:\r\nclass ListConverter : JsonConverter\r\n{\r\n    public override bool CanConvert(Type objectType)\r\n    {\r\n        return true;\r\n    }\r\n\r\n    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)\r\n    {\r\n        return new ContentA() { B = serializer.Deserialize<ContentB>(reader) }; // Construct my data back.\r\n    }\r\n\r\n    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)\r\n    {\r\n        serializer.Serialize(writer, (value as ContentA).B); // My Content.B contains all useful data.\r\n    }\r\n}\r\n\r\n// My data will be in a container, container have several lists may contain a same instance. \r\nclass Container\r\n{\r\n    public List<ContentA> ListA { get; set; }\r\n    public List<ContentA> ListB { get; set; }\r\n\r\n    public Container()\r\n    {\r\n        ListA = new List<ContentA>();\r\n        ListA.Add(new ContentA());\r\n\r\n        ListB = new List<ContentA>();\r\n        ListB.Add(ListA[0]); // A instance is in both two lists.\r\n    }\r\n}\r\n\r\n// Now I'm serializing it, my complex data may have many types so I want to include references and type names.\r\nstring Serialize()\r\n{\r\n    var settings = new JsonSerializerSettings();\r\n    settings.PreserveReferencesHandling = PreserveReferencesHandling.All;\r\n    settings.ReferenceLoopHandling = ReferenceLoopHandling.Serialize; // JSON.Net thinks I'm creating loop references, just make it happy.\r\n    settings.TypeNameHandling = TypeNameHandling.All;\r\n    settings.Formatting = Formatting.Indented;\r\n\r\n    return JsonConvert.SerializeObject(new Container(), settings);\r\n}\r\n\r\n// Result:\r\n/*\r\n{\r\n    \"$id\": \"1\",\r\n    \"$type\": \"ConsoleApplication1.Container, ConsoleApplication1\",\r\n    \"ListA\": {\r\n        \"$id\": \"2\",\r\n        \"$type\": \"System.Collections.Generic.List`1[[ConsoleApplication1.ContentA, ConsoleApplication1]], mscorlib\",\r\n        \"$values\": [\r\n            {\r\n                \"$id\": \"3\",\r\n                \"$type\": \"ConsoleApplication1.ContentB, ConsoleApplication1\",\r\n                \"SomeValue\": false\r\n            }\r\n        ]\r\n    },\r\n    \"ListB\": {\r\n        \"$id\": \"4\",\r\n        \"$type\": \"System.Collections.Generic.List`1[[ConsoleApplication1.ContentA, ConsoleApplication1]], mscorlib\",\r\n        \"$values\": [\r\n            {\r\n                \"$id\": \"3\",\r\n                \"$type\": \"ConsoleApplication1.ContentB, ConsoleApplication1\",\r\n                \"SomeValue\": false\r\n            }\r\n        ]\r\n    }\r\n}\r\n*/\r\n\r\n// What? two objects with same id=3?\r\n\r\n// Try to deserialize it:\r\nContainer Deserialize(string content)\r\n{\r\n    var settings = new JsonSerializerSettings();\r\n    settings.PreserveReferencesHandling = PreserveReferencesHandling.All;\r\n    settings.ReferenceLoopHandling = ReferenceLoopHandling.Serialize; // JSON.Net thinks I'm creating loop references, just make it happy.\r\n    settings.TypeNameHandling = TypeNameHandling.All;\r\n    settings.Formatting = Formatting.Indented;\r\n\r\n    return (Container)JsonConvert.DeserializeObject(content, settings);\r\n}\r\n\r\n// An exception is thrown:\r\n/*\r\nNewtonsoft.Json.JsonSerializationException: Error reading object reference '3'. Path 'ListB.$values[0].SomeValue', line 22, position 21.\r\n    ---> System.ArgumentException: A different value already has the Id '3'.\r\n        at Newtonsoft.Json.Utilities.BidirectionalDictionary`2.Set(TFirst first, TSecond second)\r\n        at Newtonsoft.Json.Serialization.DefaultReferenceResolver.AddReference(Object context, String reference, Object value)\r\n        at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.AddReference(JsonReader reader, String id, Object value)\r\n        --- End of inner exception stack trace ---\r\n    at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.AddReference(JsonReader reader, String id, Object value)\r\n    at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateObject(Object newObject, JsonReader reader, JsonObjectContract contract, JsonProperty member, String id)\r\n    at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)\r\n    at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)\r\n    at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent)\r\n    at Newtonsoft.Json.Serialization.JsonSerializerProxy.DeserializeInternal(JsonReader reader, Type objectType)\r\n    at Newtonsoft.Json.JsonSerializer.Deserialize[T](JsonReader reader)\r\n    at ConsoleApplication1.ListConverter.ReadJson(JsonReader reader, Type objectType, Object existingValue, JsonSerializer serializer)\r\n    at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.DeserializeConvertable(JsonConverter converter, JsonReader reader, Type objectType, Object existingValue)\r\n    at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateList(IList list, JsonReader reader, JsonArrayContract contract, JsonProperty containerProperty, String id)\r\n*/\r\n````\r\n\r\nIf I didn't use converter JSON.NET will create correct references, if I didn't include type names JSON.NET can deserialize it without problem, but if I combine them the problem will occur. "},"comment":{"url":"https://api.github.com/repos/JamesNK/Newtonsoft.Json/issues/comments/102835470","html_url":"https://github.com/JamesNK/Newtonsoft.Json/issues/570#issuecomment-102835470","issue_url":"https://api.github.com/repos/JamesNK/Newtonsoft.Json/issues/570","id":102835470,"user":{"login":"CnSimonChan","id":1330321,"avatar_url":"https://avatars.githubusercontent.com/u/1330321?v=3","gravatar_id":"","url":"https://api.github.com/users/CnSimonChan","html_url":"https://github.com/CnSimonChan","followers_url":"https://api.github.com/users/CnSimonChan/followers","following_url":"https://api.github.com/users/CnSimonChan/following{/other_user}","gists_url":"https://api.github.com/users/CnSimonChan/gists{/gist_id}","starred_url":"https://api.github.com/users/CnSimonChan/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/CnSimonChan/subscriptions","organizations_url":"https://api.github.com/users/CnSimonChan/orgs","repos_url":"https://api.github.com/users/CnSimonChan/repos","events_url":"https://api.github.com/users/CnSimonChan/events{/privacy}","received_events_url":"https://api.github.com/users/CnSimonChan/received_events","type":"User","site_admin":false},"created_at":"2015-05-17T18:57:07Z","updated_at":"2015-05-17T18:57:07Z","body":"My class overrode `Equals()` method so a `ContentA` and a `ContentB` will be equivalent if their have same data.\r\n````C#\r\n[JsonConverter(typeof(ListConverter))]\r\nclass ContentA {\r\n    public ContentB B { get; set; }\r\n    public override Equals(object other) {\r\n        // ......\r\n        if (other is ContentB)\r\n            return this.B.Equals(other);\r\n        // ......\r\n    }\r\n````\r\nBut JSON.NET thinks it's self reference because `JsonSerializerInternalWriter._serializeStack` already contained a `ContentA` which is *equals* to the converted `ContentB`.\r\n\r\nMaybe `JsonSerializerInternalWriter.SerializeConvertable()` should not add the source object to `_serializeStack`? Or maybe `JsonSerializerInternalWriter.CheckForCircularReference()` should check equability by `ReferenceEquals`?\r\n\r\nIn fact after this fix my code can never finish, I'm trying to build a minimal code example."}}