NEST的默认JSON序列化了解如何正确序列化所有请求和响应类型,以及正确处理您的POCO。 然而,有时候,您可能希望通过提供自己的序列化程序或修改NEST的序列化器的行为来改变此行为。
改变序列化器
修改默认序列化器
NEST使用JSON.Net将JSON的响应序列化和反序列化。
尽管JSON.Net做好了序列化,但是由于某种原因,您可能希望使用自己的JSON序列化程序。 Elasticsearch.Net和NEST可以轻松地用自己的名字替换默认的序列化器。
所需的主要组件是提供IElasticsearchSerializer
的实现
public class CustomSerializer : IElasticsearchSerializer
{
public T Deserialize(Stream stream)
{
// provide deserialization implementation
throw new NotImplementedException();
}
public Task DeserializeAsync(Stream responseStream, CancellationToken cancellationToken = default(CancellationToken))
{
// provide an asynchronous deserialization implementation
throw new NotImplementedException();
}
public void Serialize(object data, Stream writableStream, SerializationFormatting formatting = SerializationFormatting.Indented)
{
// provide a serialization implementation
throw new NotImplementedException();
}
public IPropertyMapping CreatePropertyMapping(MemberInfo memberInfo)
{
// provide an implementation, if the serializer can decide how properties should be mapped.
// Otherwise return null.
return null;
}
}
对于Elasticsearch.Net,IElasticsearchSerializer
的一个实现是所有需要的,一个委托可以被传递给ConnectionConfiguration
,该配置将被调用来构造一个序列化器的一个实例
var pool = new SingleNodeConnectionPool(new Uri("http://localhost:9200"));
var connection = new HttpConnection();
var connectionConfiguration =
new ConnectionConfiguration(pool, connection, configuration => new CustomSerializer());
var lowlevelClient = new ElasticLowLevelClient(connectionConfiguration);
委托通过ConnectionConfiguration
并创建一个序列化器
然而,使用NEST,除了实现IElasticsearchSerializer
之外,还需要实现ISerializerFactory
public class CustomSerializerFactory : ISerializerFactory
{
public IElasticsearchSerializer Create(IConnectionSettingsValues settings) => new CustomSerializer();
public IElasticsearchSerializer CreateStateful(IConnectionSettingsValues settings, JsonConverter converter) =>
new CustomSerializer();
}
通过实现ISerializerFactory
可以创建我们的自定义序列化程序的实例,将其连接到ConnectionSettings
是直接的
var pool = new SingleNodeConnectionPool(new Uri("http://localhost:9200"));
var connection = new HttpConnection();
var connectionSettings =
new ConnectionSettings(pool, connection, new CustomSerializerFactory());
var client = new ElasticClient(connectionSettings);
在客户端中如何配置自定义序列化的实现在下一个主要版本中可能会发生更改。 NEST严重依赖有状态的反序列化器,可以从原始请求中获取详细信息,以获得诸如协变搜索结果的专门功能。
您可能已经注意到,此要求以CreateStateful
方法签名的形式泄漏到ISerializerFactory
抽象中。 有意图替代或至少内部化NEST在未来和在此过程中的JSON.Net的使用,简化如何自定义序列化可以集成。
这提供了有关如何实现自己的自定义序列化的详细信息,但是NEST客户端用户中更常见的情况是希望更改默认JSON.Net序列化器的序列化设置。 看看修改默认的序列化器,看看如何做到这一点。
在更改序列化器中,您看到了如何将自己的序列化器实现提供给NEST。 更常见的情况是希望在默认的JSON.Net序列化器上更改设置。
有几种方法可以做到这一点,这取决于你需要改变什么。
ISerializerFactory
的默认实现允许传递一个委托,可以更改由工厂创建的JSON.Net序列化器的设置
var pool = new SingleNodeConnectionPool(new Uri("http://localhost:9200"));
var connection = new HttpConnection();
var connectionSettings =
new ConnectionSettings(pool, connection, new SerializerFactory((settings, values) =>
{
settings.NullValueHandling = NullValueHandling.Include;
settings.TypeNameHandling = TypeNameHandling.Objects;
}));
var client = new ElasticClient(connectionSettings);
委托将被JsonSerializerSettings
和IConnectionSettingsValues
传递
这里,JSON.Net序列化器被配置为在序列化到JSON对象结构时始终序列化空值并包含.NET类型名称。
如果您需要更多的控制权来将委托提供给SerializerFactory
,您还可以实现自己的ISerializerFactory
,并从默认的JsonNetSerializer
派生一个IElasticsearchSerializer
。
这是一个这样做的例子,有效地实现了与上一个例子相同的配置。 首先,实现了定制工厂和序列化器
public class CustomJsonNetSerializerFactory : ISerializerFactory
{
public IElasticsearchSerializer Create(IConnectionSettingsValues settings)
{
return new CustomJsonNetSerializer(settings);
}
public IElasticsearchSerializer CreateStateful(IConnectionSettingsValues settings, JsonConverter converter)
{
return new CustomJsonNetSerializer(settings, converter);
}
}
public class CustomJsonNetSerializer : JsonNetSerializer
{
public CustomJsonNetSerializer(IConnectionSettingsValues settings) : base(settings)
{
base.OverwriteDefaultSerializers(ModifyJsonSerializerSettings);
}
public CustomJsonNetSerializer(IConnectionSettingsValues settings, JsonConverter statefulConverter) :
base(settings, statefulConverter)
{
base.OverwriteDefaultSerializers(ModifyJsonSerializerSettings);
}
private void ModifyJsonSerializerSettings(JsonSerializerSettings settings, IConnectionSettingsValues connectionSettings)
{
settings.NullValueHandling = NullValueHandling.Include;
settings.TypeNameHandling = TypeNameHandling.Objects;
}
}
然后,创建一个新的工厂实例到ConnectionSettings
var pool = new SingleNodeConnectionPool(new Uri("http://localhost:9200"));
var connection = new HttpConnection();
var connectionSettings =
new ConnectionSettings(pool, connection, new CustomJsonNetSerializerFactory());
var client = new ElasticClient(connectionSettings);
任何派生自JsonNetSerializer
的自定义序列化器希望更改JSON.Net序列化器的设置,都必须使用派生序列化器的构造函数中的OverwriteDefaultSerializers
方法。
NEST包括许多对IContractResolver
进行的自定义更改,JSON.Net序列化器用于解决类型的序列化契约。 此类更改的示例有:
允许具体类型的契约从它们实现的接口继承
专门处理词典以确保字典键逐字排列
显式实现的接口属性在请求中被序列化
因此,IContractResolver
的这些更改不会被源自JsonNetSerializer的序列化器覆盖很重要。