How Do You "Really" Serialize Circular Referencing Objects With Newtonsoft.Json? How Do You "Really" Serialize Circular Referencing Objects With Newtonsoft.Json? json json

How Do You "Really" Serialize Circular Referencing Objects With Newtonsoft.Json?


Yes, using PreserveReferencesHandling.Objects is really the best way to serialize an object graph with circular references, because it produces the most compact JSON and it actually preserves the reference structure of the object graph. That is, when you deserialize the JSON back to objects (using a library that understands the $id and $ref notation), each reference to a particular object will point to the same instance of that object, rather than having multiple instances with the same data.

In your case the problem is that your client side parser does not understand the $id and $ref notation produced by Json.Net, so the references are not being resolved. This can be fixed by using a javascript method to reconstruct the object references after deserializing the JSON. See here and here for examples.

Another possibility which might work, depending on your situation, is to set ReferenceLoopHandling to Ignore when serializing instead of setting PreserveReferencesHandling to Objects. This is not a perfect solution though. See this question for a detailed explanation of the differences between using ReferenceLoopHandling.Ignore and PreserveReferencesHandling.Objects.


I wrote a minimal program to test this. Here is my github: https://github.com/assafwo1/TestSerializeJsonObjects. Here is the code:

using Newtonsoft.Json;using System.Diagnostics;namespace TestSerializeJsonObjects{    class Program    {        public class Node        {            public Node Next { get; set; }        }        static void Main(string[] args)        {            // create new node            var head = new Node();            // point its "next" field at itself            head.Next = head;            // this is now the smallest circular reference data structure possible             // assert that head next is head            Debug.Assert(head.Next == head);            // save to string            var s = JsonConvert.SerializeObject(head, new JsonSerializerSettings            {                PreserveReferencesHandling = PreserveReferencesHandling.Objects            });            // get from string            var head2 = JsonConvert.DeserializeObject<Node>(s, new JsonSerializerSettings            {                PreserveReferencesHandling = PreserveReferencesHandling.Objects            });            // assert that head2 next is head2            Debug.Assert(head2.Next == head2);            // done        }    }}