using System.Collections.Generic;
using Newtonsoft.Json.Serialization;
public static void Main()
""PhoneNumber"": ""(555)555-5555"",
""PhoneNumber"": ""(555)555-5555"",
var jsonSerializerSettings = new JsonSerializerSettings()
ReferenceResolver = new ReferenceResolverWithNames()
var deserializedPersons = JsonConvert.DeserializeObject<List<Person>>(json, jsonSerializerSettings);
Console.WriteLine(((Person)deserializedPersons[0]).Cat.Name);
public string Name {get; set;}
public string PhoneNumber {get; set;}
public Person Partner {get; set;}
public Cat Cat {get; set;}
public string Name {get; set;}
public class ReferenceResolverWithNames : IReferenceResolver
private readonly ReferenceCollection _collection = new ReferenceCollection();
public object ResolveReference(object context, string reference)
return _collection.Get(reference);
public string GetReference(object context, object value)
if (_collection.Contains(value)) return _collection.GetReference(value);
return _collection.Add(value);
public bool IsReferenced(object context, object value)
return _collection.Contains(value);
public void AddReference(object context, string reference, object value)
_collection.Add(value, reference);
class ReferenceCollection
private readonly Dictionary<Type, Dictionary<string, object>> _referenceDictionary = new Dictionary<Type, Dictionary<string, object>>();
internal bool Contains(object obj)
var objType = obj.GetType();
Dictionary<string, object> objDictionary;
if (_referenceDictionary.TryGetValue(objType, out objDictionary))
return objDictionary.ContainsValue(obj);
internal string Add(object obj, string key = null)
var objType = obj.GetType();
Dictionary<string, object> objDictionary;
if (!_referenceDictionary.TryGetValue(objType, out objDictionary))
_referenceDictionary.Add(objType, objDictionary = new Dictionary<string, object>());
var objPropertyInfo = objType.GetProperty("Name");
if (objPropertyInfo != null) key = (string) objPropertyInfo.GetValue(obj);
else key = objDictionary.Count.ToString();
if (!objDictionary.ContainsKey(key)) objDictionary.Add(key, obj);
internal object Get(string reference)
var typeDictionary = _referenceDictionary.Values.SingleOrDefault(typeDict => typeDict.ContainsKey(reference));
if (typeDictionary == null) throw new InvalidOperationException(string.Format(@"value with for $ref: ""{0}"" hasn't been deserialized yet.", reference));
return typeDictionary[reference];
internal string GetReference(object obj)
var objType = obj.GetType();
var objPropertyInfo = objType.GetProperty("Name");
if (objPropertyInfo != null) return (string)objPropertyInfo.GetValue(obj);
Dictionary<string, object> objDictionary;
if (!_referenceDictionary.TryGetValue(objType, out objDictionary))
_referenceDictionary.Add(objType, objDictionary = new Dictionary<string, object>());
return objDictionary.Count.ToString();