Nest: Add a custom ContractResolver

Hi guys,

How can I add a custom ContractResolver in order prevent calling default constructor?

Tried to do this, but it does not work:

public class MyJsonNetSerializer : JsonNetSerializer
{
...

protected override void ModifyJsonSerializerSettings(JsonSerializerSettings settings)
    {
      settings.DateParseHandling = DateParseHandling.DateTimeOffset;
      settings.Converters.Add(new DictionaryJsonConverter());
      settings.ContractResolver = new NoConstructorCreationContractResolver();
    }
}


_settings = new ConnectionSettings(_connectionPool, s => new MyJsonNetSerializer(s));      
_client = new ElasticClient(_settings);

Thanks

hey @Denis_Lamanov, what version of NEST are you using?

Hi @forloop,

I'm using the latest version from NuGeT: 2.0.0.0

Thanks

You can't add a custom IContractResolver in NEST; This is intentional because the ElasticContractResolver that is used by the default IElasticsearchSerializer has a few features that are used internally

  1. constructs JsonConverter instances in some scenarios that require state at the point of deserialization
  2. handles not serializing empty collections or collections that only contain null items
  3. gets property names from property mappings configured with NEST mapping attributes
  4. builds serialization models for concrete types from implemented interfaces

You can however add your own JsonConverter instances, if you'd like to handle serialization for certain types in a particular way. Here's an example of defining our own converter for handling DateTime, DateTimeOffset and their nullable counterparts

void Main()
{
    var pool = new SingleNodeConnectionPool(new Uri("http://localhost:9200"));
    var connectionSettings = new ConnectionSettings(
        pool, 
        new HttpConnection(), 
        new SerializerFactory(settings => new CustomSerializer(settings)));
				
    var client = new ElasticClient(connectionSettings);
}

public class CustomSerializer : JsonNetSerializer
{
    public CustomSerializer(IConnectionSettingsValues settings) : base(settings)
    {
    }

    protected override IList<Func<Type, JsonConverter>> ContractConverters => 
        new List<Func<Type, JsonConverter>>
        {
            t => (t == typeof(DateTime) ||
                  t == typeof(DateTime?) ||
                  t == typeof(DateTimeOffset) ||
                  t == typeof(DateTimeOffset?))
                ? new Newtonsoft.Json.Converters.IsoDateTimeConverter { DateTimeStyles = System.Globalization.DateTimeStyles.AdjustToUniversal } 
                : null
        };
}

You can also write your own IElasticsearchSerializer implementation too.

What do you need to do in NoConstructorCreationContractResolver? Wondering if it's something that can be achieved another way.

Hi @forloop,

Perfect full answer, working on it)

Thanks