Serialize/Deserialize complex type to Json with object references and dictionaries that have complex type as key
c#, json, json.net, serialization
Solution
Json.NET supports handling object references: Preserving Object References
Complex type dictionary keys can be handled by creating a TypeConverter that will convert the type to and from a string. Json.NET will use that string as the dictionary key.
Problem
I am trying to serialize/deserialize a complex type. I want object references to be preserved, meaning that if the instance of an object is referenced multiple times in the object graph, during deserialization I want the deserializer to only create that instance once and have it referenced multiple times (vs. create that object instance multiple times). The second thing I need the system to deal with is a dictionary where the key is a complex type itself. I was able to achieve both with the DataContractSerializer serializing to XML. However I am failing to find any Json serializer that can do this. I tried Json.NET and ServiceStack, but no luck. See the sample code below: ``` using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Runtime.Serialization; using System.Text; using System.Xml; using Newtonsoft.Json; namespace Serialization { class Program { static void Main(string[] args) { var transportModel = CreateSampleModel(); //Serialize with DataContractSerializer var serializer = new DataContractSerializer(typeof(TransportModel), null, int.MaxValue, false, true, null, null); string serializedObjectXml; using (var sw = new StringWriter()) { using (var writer = new XmlTextWriter(sw)) { serializer.WriteObject(writer, transportModel); writer.Flush(); serializedObjectXml = sw.ToString(); } } //Deserialize with DataContractSerializer byte[] byteArray = Encoding.ASCII.GetBytes(serializedObjectXml); var stream = new MemoryStream(byteArray); var deserializedObjectXml = serializer.ReadObject(stream); //Serialize with Json.NET var serializedObjectJson=JsonConvert.SerializeObject(transportModel); //Deserialize with Json.NET - this fails because of the key in the dictionary being a complex type var deserializedObjectJson = JsonConvert.DeserializeObject(serializedObjectJson); } static TransportModel CreateSampleModel() { var transportModel = new TransportModel(); // dests var fra = new Destination { Id = 0, Name = "FRA", Demand = 900 }; var det = new Destination { Id = 1, Name = "DET", Demand = 1200 }; var dests = new List<Destination> { fra, det}; //origs var gary = new Origin { Id = 0, Name = "GARY", Supply = 1400, Cost = new Dictionary<Destination, int>{ {fra, 39}, {det, 14} } }; var origs = new List<Origin> { gary}; transportModel.Destinations = dests; transportModel.Origins = origs; return transportModel; } } [DataContract] class Destination { [DataMember] public int Id { get; set; } [DataMember] public string Name { get; set; } [DataMember] public int Demand { get; set; } } [DataContract] class Origin { [DataMember] public int Id { get; set; } [DataMember] public string Name { get; set; } [DataMember] public int Supply { get; set; } [DataMember] public Dictionary<Destination, int> Cost { get; set; } } [DataContract] class TransportModel { [DataMember] public List<Origin> Origins; [DataMember] public List<Destination> Destinations; public TransportModel() { Origins = new List<Origin>(); Destinations = new List<Destination>(); } } } ```