JsonConvert.SerializeObject - 自定义 ContracteResolver 不调用 CreateProperty 进行多次调用

Don*_*ers 5 json.net jsonconvert

我有一个自定义的 ContracteResolver,并且得到了不可预测的结果。

使用调试器,我发现当我序列化时,每个属性都会调用解析器的CreateProperty方法。但是,如果我连续进行两次调用,则第二次调用时不会调用 CreateProperty 方法。我在 CreateProperty 中的断点在第二遍时从未被击中,而是在第一次被击中。

这是我的设置:

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

_payload = JsonConvert.SerializeObject(this.Data, Formatting.None, settings);
Run Code Online (Sandbox Code Playgroud)

我的源值(this.Data)对于这两个调用是不同的。两次调用的结果 (_payload) 也不同。我认为没有任何内容被缓存。

我看到了由自定义 ContentNegotiator 引起的类似问题,但我不使用它。

为什么 CreateProperty 在第二遍时不会被命中?

Bri*_*ers 5

DefaultContractResolver类缓存每个对象类型协定以获得最佳性能。您可以在源代码中看到这一点,它在构造函数内创建缓存:

public DefaultContractResolver()
{
   ...
    _contractCache = new ThreadSafeStore<Type, JsonContract>(CreateContract);
}
Run Code Online (Sandbox Code Playgroud)

以及在解决每种类型的合同时如何使用它:

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

    return _contractCache.Get(type);
}
Run Code Online (Sandbox Code Playgroud)

因此,如果:

  1. 您的自定义解析器派生自DefaultContractResolver,并且
  2. 您每次都使用相同的解析器实例,并且
  3. 您的数据对象具有相同的类型(即使它们具有不同的数据)

那么这是正常的并且预计CreateProperty只会在第一次序列化时被调用。

  • 差不多就是答案了。我没有使用相同的解析器实例,但我继承自 CamelCasePropertyNamesContractResolver,它缓存在静态变量中。如果我从 DefaultContractResolver 继承,它可以工作,但我会丢失我的 CamelCase。如何使用两个解析器?我正在根据数据添加和删除字段。 (4认同)