JsonConvert.SerializeObject - Custom ContracteResolver not calling CreateProperty for multiple calls

Viewed 850

I have a custom ContracteResolver and I am getting unpredictable results.

Using the debugger, I see that when I serialize the CreateProperty method of the resolver is called for every property. However, if I make 2 calls back to back the CreateProperty method is not called on the second call. My breakpoint in CreateProperty is never hit on the second pass, it is hit on the first.

Here is my setup:

IContractResolver contractResolver = new ShouldSerializeContractResolver(fieldsToSerialize, this.Data);
var settings = new JsonSerializerSettings()
{
ContractResolver = contractResolver
};

_payload = JsonConvert.SerializeObject(this.Data, Formatting.None, settings);

My source value (this.Data) is different for both calls. The results (_payload) is also different for both call. I don't think anything is being cached.

I saw a similar question that was caused by a custom ContentNegotiator, but I don't use that.

Why would CreateProperty not be hit on the second pass?

1 Answers

The DefaultContractResolver class caches the contracts for each object type for best performance. You can see this in the source code where it creates the cache inside the constructor:

public DefaultContractResolver()
{
   ...
    _contractCache = new ThreadSafeStore<Type, JsonContract>(CreateContract);
}

And also how it is used when the contracts are resolved for each type:

public virtual JsonContract ResolveContract(Type type)
{
    ValidationUtils.ArgumentNotNull(type, nameof(type));

    return _contractCache.Get(type);
}

So if:

  1. your custom resolver derives from DefaultContractResolver, and
  2. you are using the same resolver instance each time, and
  3. your data objects are of the same type (even if they have different data)

then it is normal and expected that CreateProperty will only be called for the first serialization.

Related