This can be done with a custom ContractResolver
that sets JsonContract.IsReference == false
by overriding DefaultContractResolver.CreateContract()
:
public class DisableReferencePreservationContractResolver : DefaultContractResolver
{
readonly HashSet<Type> types;
public DisableReferencePreservationContractResolver(IEnumerable<Type> types)
{
this.types = new HashSet<Type>(types);
}
bool ContainsType(Type type)
{
return types.Contains(type);
//return types.Any(t => t.IsAssignableFrom(type));
}
bool? GetIsReferenceOverride(Type type)
{
return ContainsType(type) ? false : (bool?)null;
}
protected override JsonContract CreateContract(Type objectType)
{
// Disable IsReference for this type of object
var contract = base.CreateContract(objectType);
contract.IsReference = contract.IsReference ?? GetIsReferenceOverride(objectType);
return contract;
}
}
The constructor should be passed a list of types for which reference information is to be disabled. Note that I am excluding this information for instances of the exact type(s) passed into the contract resolver. If you want to exclude this information from instances of derived types as well, you could modify ContainsType()
as follows:
bool ContainsType(Type type)
{
return types.Any(t => t.IsAssignableFrom(type));
}
Note also the contract resolver disables PreserveReferencesHandling
when set in JsonSerializerSettings
, but not when set directly with serialization attributes such as [JsonObject(IsReference = true)]
or [JsonProperty(IsReference = true)]
on the external types.
Sample fiddle.
You might want to cache the contract resolver for best performance.