如何在 Elasticsearch NEST 中序列化 JToken 或 JObject 类型的属性?
How do I serialize properties of type JToken or JObject in Elasticsearch NEST?
我正在将 Elasticsearch 引入到 C# API 项目中。我想利用现有 API 模型作为搜索文档,其中许多模型允许添加自定义数据点。这些是使用 Json.NET 中的 JObject 类型实现的。例如:
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public JObject ExtraProps { get; set; }
}
这允许用户像这样发送 JSON 请求正文,效果很好:
{
"Id": 123,
"Name": "Thing",
"ExtraProps": {
"Color": "red",
"Size": "large"
}
}
但是,如果我在 NEST 中使用它作为文档类型,那些额外的属性会以某种方式丢失它们的值,序列化为:
{
"Id": 123,
"Name": "Thing",
"ExtraProps": {
"Color": [],
"Size": []
}
}
将 [Nest.Object]
属性添加到 ExtraProps
并没有改变行为。据我了解,NEST 在内部使用 Json.NET,所以我不希望它在 Json.NET 类型上有问题。有没有相对简单的修复方法?
以下是我正在权衡的一些选项:
使用custom serialization。我开始走这条路,感觉比它应该的要复杂得多,而且我从来没有让它工作过。
将 JObject
映射到 Dictionary<string, object>
。我已经验证了这项工作,但如果有嵌套对象(可能有),我需要用递归来增强它。而且,理想情况下,我希望它能与更通用的 JToken 类型一起使用。这是我倾向于的选项,但同样,它感觉比应该的更复杂。
使用 "Low Level" client 甚至原始 HTTP 调用。不可否认,我还没有探索过这个,但如果它真的 simpler/cleaner 比其他选择,我愿意接受它。
将此报告为错误。无论如何,我可能会这样做。我只是有一种预感 应该 与 JObject
或任何开箱即用的 JToken
一起工作,除非出于某种原因这是预期的行为。
这是 NEST 的预期行为 6.x。
NEST 使用 Json.NET 进行序列化。然而,在 NEST 6.x 中,这种依赖性通过
在 NEST 程序集中内化了
- IL 将所有 Json.NET 类型合并到 NEST 程序集中
- 将 Newtonsoft.Json 中的类型重命名为 Nest.Json
- 标记所有类型
internal
There's a blog post with further details 解释这一变化背后的动机。
在处理 Json.NET 类型时,例如 Newtonsoft.Json.Linq.JObject
,Json.NET 对 serialization/deserialization 的这些类型有特殊处理。使用 NEST 6.x,内部化 Json.NET 不知道如何专门处理 Newtonsoft.Json.Linq.JObject
,因为内部化 Json.NET 中的所有类型都已重命名空间到 Nest.Json
命名空间。
要支持 Json.NET 类型,需要连接使用 Json.NET 序列化文档的序列化程序。 NEST.JsonNetSerializer
nuget package 的创建就是为了帮助解决这个问题。只需将对 NEST.JsonNetSerializer
的引用添加到您的项目,然后按如下方式连接序列化程序
// choose the appropriate IConnectionPool for your use case
var pool = new SingleNodeConnectionPool(new Uri("http://localhost:9200"));
var connectionSettings =
new ConnectionSettings(pool, JsonNetSerializer.Default);
var client = new ElasticClient(connectionSettings);
有了这个地方,具有 JObject
属性的文档将按预期序列化。
我正在将 Elasticsearch 引入到 C# API 项目中。我想利用现有 API 模型作为搜索文档,其中许多模型允许添加自定义数据点。这些是使用 Json.NET 中的 JObject 类型实现的。例如:
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public JObject ExtraProps { get; set; }
}
这允许用户像这样发送 JSON 请求正文,效果很好:
{
"Id": 123,
"Name": "Thing",
"ExtraProps": {
"Color": "red",
"Size": "large"
}
}
但是,如果我在 NEST 中使用它作为文档类型,那些额外的属性会以某种方式丢失它们的值,序列化为:
{
"Id": 123,
"Name": "Thing",
"ExtraProps": {
"Color": [],
"Size": []
}
}
将 [Nest.Object]
属性添加到 ExtraProps
并没有改变行为。据我了解,NEST 在内部使用 Json.NET,所以我不希望它在 Json.NET 类型上有问题。有没有相对简单的修复方法?
以下是我正在权衡的一些选项:
使用custom serialization。我开始走这条路,感觉比它应该的要复杂得多,而且我从来没有让它工作过。
将
JObject
映射到Dictionary<string, object>
。我已经验证了这项工作,但如果有嵌套对象(可能有),我需要用递归来增强它。而且,理想情况下,我希望它能与更通用的 JToken 类型一起使用。这是我倾向于的选项,但同样,它感觉比应该的更复杂。使用 "Low Level" client 甚至原始 HTTP 调用。不可否认,我还没有探索过这个,但如果它真的 simpler/cleaner 比其他选择,我愿意接受它。
将此报告为错误。无论如何,我可能会这样做。我只是有一种预感 应该 与
JObject
或任何开箱即用的JToken
一起工作,除非出于某种原因这是预期的行为。
这是 NEST 的预期行为 6.x。
NEST 使用 Json.NET 进行序列化。然而,在 NEST 6.x 中,这种依赖性通过
在 NEST 程序集中内化了- IL 将所有 Json.NET 类型合并到 NEST 程序集中
- 将 Newtonsoft.Json 中的类型重命名为 Nest.Json
- 标记所有类型
internal
There's a blog post with further details 解释这一变化背后的动机。
在处理 Json.NET 类型时,例如 Newtonsoft.Json.Linq.JObject
,Json.NET 对 serialization/deserialization 的这些类型有特殊处理。使用 NEST 6.x,内部化 Json.NET 不知道如何专门处理 Newtonsoft.Json.Linq.JObject
,因为内部化 Json.NET 中的所有类型都已重命名空间到 Nest.Json
命名空间。
要支持 Json.NET 类型,需要连接使用 Json.NET 序列化文档的序列化程序。 NEST.JsonNetSerializer
nuget package 的创建就是为了帮助解决这个问题。只需将对 NEST.JsonNetSerializer
的引用添加到您的项目,然后按如下方式连接序列化程序
// choose the appropriate IConnectionPool for your use case
var pool = new SingleNodeConnectionPool(new Uri("http://localhost:9200"));
var connectionSettings =
new ConnectionSettings(pool, JsonNetSerializer.Default);
var client = new ElasticClient(connectionSettings);
有了这个地方,具有 JObject
属性的文档将按预期序列化。