概述
NEST
的默认JSON序列化知道如何正确序列化所有请求和响应类型,以及正确处理实体映射。然而,有时你可能希望通过提供自己的序列化程序或修改NEST
的序列化程序的行为来改变默认的行为。NEST
提供了自定义序列化的能力。
在NEST
6.0或者更早的版本中,序列化依赖的是SimpleJson
和Newtonsoft.Json
这两个类库,从NEST
7.0开始,这两个类库被完全移除了。取而代之的是Utf8Json
,这是一个直接使用UTF-8二进制的快速序列化程序。
注入新的序列化器
你可以注入一个单独的仅在序列化_source
,_fields
时被调用的序列化器,或者用户提供的值被写入和返回的任何地方。
在NEST
内部,这个序列化器被称作SourceSerializer
。NEST
内部还提供了另外一个叫ReqeustResponseSerializer
的序列化器。这个序列化器负责序列化NEST
中的请求和响应类型。
如果需要注入自定义的SourceSerializer
序列化器,你只要实现IElasticsearchSerializer
这个接口即可:
public class VanillaSerializer : IElasticsearchSerializer
{
public T Deserialize<T>(Stream stream) => throw new NotImplementedException();
public object Deserialize(Type type, Stream stream) => throw new NotImplementedException();
public Task<T> DeserializeAsync<T>(Stream stream, CancellationToken cancellationToken = default(CancellationToken)) =>
throw new NotImplementedException();
public Task<object> DeserializeAsync(Type type, Stream stream, CancellationToken cancellationToken = default(CancellationToken)) =>
throw new NotImplementedException();
public void Serialize<T>(T data, Stream stream, SerializationFormatting formatting = SerializationFormatting.Indented) =>
throw new NotImplementedException();
public Task SerializeAsync<T>(T data, Stream stream, SerializationFormatting formatting = SerializationFormatting.Indented,
CancellationToken cancellationToken = default(CancellationToken)) =>
throw new NotImplementedException();
}
然后,在ConnectionSettings
的构造函数中传入自定义的序列化器,如:
var pool = new SingleNodeConnectionPool(new Uri("http://localhost:9200"));
var connectionSettings = new ConnectionSettings(
pool,
sourceSerializer: (builtin, settings) => new VanillaSerializer());
var client = new ElasticClient(connectionSettings);
JsonNetSerializer
NEST
还提供了一个单独的NEST.JsonNetSerializer
包来结合Json.NET
实现自定义SourceSerializer
,它可以智能地将NEST
的类型序列化成内置的RequestResposeSerializer
。NEST.JsonNetSerializer
在以下情况时可能很有用:
- 你希望使用
Json.NET
来控制文档和值如何从Elasticsearch存储和检索。 - 在你的文档中使用类似
JObject
这样的Newtonsoft.Json.Linq
数据类型时。
你可以使用如下方法来配置这个自定义源序列化程序:
var pool = new SingleNodeConnectionPool(new Uri("http://localhost:9200"));
var connectionSettings =
new ConnectionSettings(pool, sourceSerializer: JsonNetSerializer.Default);
var client = new ElasticClient(connectionSettings);
JsonNetSerializer.Default
只是传递委托的语法糖:
var pool = new SingleNodeConnectionPool(new Uri("http://localhost:9200"));
var connectionSettings = new ConnectionSettings(
pool,
sourceSerializer: (builtin, settings) => new JsonNetSerializer(builtin, settings));
var client = new ElasticClient(connectionSettings);
JsonNetSerializer
的构造函数接受几个方法,这些方法允许你控制JsonSerializerSettings
并修改Json.NET
解析器的配置,如下:
var pool = new SingleNodeConnectionPool(new Uri("http://localhost:9200"));
var connectionSettings =
new ConnectionSettings(pool, sourceSerializer: (builtin, settings) => new JsonNetSerializer(
builtin, settings,
() => new JsonSerializerSettings { NullValueHandling = NullValueHandling.Include },
resolver => resolver.NamingStrategy = new SnakeCaseNamingStrategy()
));
var client = new ElasticClient(connectionSettings);
派生序列化器
如果你想更多地自定义序列化器,你可以从ConnectionSettingsAwareSerializerBase
基类派生,然后重写CreateJsonSerializerSettings
和ModifyContractResolver
方法 :
public class MyFirstCustomJsonNetSerializer : ConnectionSettingsAwareSerializerBase
{
public MyFirstCustomJsonNetSerializer(IElasticsearchSerializer builtinSerializer, IConnectionSettingsValues connectionSettings)
: base(builtinSerializer, connectionSettings) { }
protected override JsonSerializerSettings CreateJsonSerializerSettings() =>
new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Include
};
protected override void ModifyContractResolver(ConnectionSettingsAwareContractResolver resolver) =>
resolver.NamingStrategy = new SnakeCaseNamingStrategy();
}
在MyCustomJsonNetSerializer
类中,你可以:
- 使用
Json.NET
的蛇形属性命名策略 - 设置序列化时包含
null
值的属性
以上设置不会影响NEST
自己的类型序列化方式。以下示例展示如何使用自定义序列化器来序列化嵌套的类型:
public class MyDocument
{
public int Id { get; set; }
public string Name { get; set; }
public string FilePath { get; set; }
public int OwnerId { get; set; }
public IEnumerable<MySubDocument> SubDocuments { get; set; }
}
public class MySubDocument
{
public string Name { get; set; }
}
在ConnectionSettings
构造函数中配置自定义序列化器:
var pool = new SingleNodeConnectionPool(new Uri("http://localhost:9200"));
var connectionSettings = new ConnectionSettings(
pool,
connection: new InMemoryConnection(),
sourceSerializer: (builtin, settings) => new MyFirstCustomJsonNetSerializer(builtin, settings))
.DefaultIndex("my-index");
var client = new ElasticClient(connectionSettings);
现在,创建一个文档索引:
var document = new MyDocument
{
Id = 1,
Name = "My first document",
OwnerId = 2
};
var ndexResponse = client.IndexDocument(document);
序列化的结果为:
{
"id": 1,
"name": "My first document",
"file_path": null,
"owner_id": 2,
"sub_documents": null
}
序列化出来的JSON字符串遵循我们配置的MyCustomJsonNetSerializer
序列化器的规则。
发表评论
登录用户才能发表评论, 请 登 录 或者 注册