I am using JSON.NET 6.0.3. I have changed PreserveReferences option as follows:
HttpConfiguration.Formatters.JsonFormatter.SerializerSettings.PreserveReferencesHandling = PreserveReferencesHandling.Objects;
My object graph resembles the following:
public class CarFromManufacturer
{
public int CarID { get; set; }
public string Make { get; set; }
public string Model { get; set; }
public CarManufacturer Manufacturer { get; set; }
}
public class CarManufacturer
{
public int ManufacturerID { get; set; }
public string Name { get; set; }
}
My WebAPI controller is returning the result set of IEnumerable[CarFromManufacturer]. So the result could be a list of 5 cars from two unique manufacturer objects. I am expecting the JSON result to list each manufacturer only once fully serialized and then subsequent uses of the same Manufacturer to be $ref ID to the original's $id. That is not happening.
Even though I can't find a single piece of documentation that speaks about how equality is established for the ReferenceResolver, I've implemented IEquatable along with override of base.Equals and base.GetHashCode() with no luck.
I'd like to avoid implementing my own IReferenceResolver because have very similar object graphs working as expected in the same project.
The only thing I can think of is that I am using factory objects and instead of creating each unique CarManufacturer first, then creating the instances of CarFromManufacturer passing in CarManufacturer... i am creating a new instance of the CarManufacturer. This would explain why the objects aren't equal, but that's why I implemented IEquatable and overrides of base.Equals(object) and base.GetHashCode().
I've looked into the source for DefaultReferenceResolver and it uses the default constructor of BidirectionalDictionary which uses EqualityComparer.Default which, from MSDN documentation, uses the T's implementation of IEquatable if it exists, or otherwise uses T's base.Equals() implementation.... all of this would lead me to believe that IEquatable in CarManufacturer should fix my problem. However, placing breakpoints in CarManufacturer.Equals() and GethashCode() never hit..
JSON.NET's logic for resolving references by default just compares references using this comparer.
If you want to compare objects in a different manner, you'll have to implement a custom
IReferenceResolver
.Here's an example that takes an
IEqualityComparer<T>
to accommodate your use case:Json.Net will call the Equals method on the objects being compared. In certain scenarios you may not want this however for example when it is checking for circular references it does the same whereas it may be more ideal to check for reference equality. They do this however to give the developer full control by overridding the Equals method in their classes.
You can override the default implementation. For example to make this a reference equality you would do the following: