3

I'm having the issue where the $id and $ref properties in the generated JSON are not accepted by the external resource. But as we need this internally I can't just disable PreserveReferencesHandling globally.

How can I disable this just for a single type? I've seen the [JsonObject] attribute but as this class is from an external source I can't add the attribute to it... I looked into the IContractResolver but couldn't figure out how to disable the reference handling there.

Thanks!

  • JSON.Net v10.0.2
TS.
  • 381
  • 6
  • 13

1 Answers1

1

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.

dbc
  • 104,963
  • 20
  • 228
  • 340