如何在 Elasticsearch NEST 中序列化 JToken 或 JObject 类型的属性?

2024-04-19

我正在将 Elasticsearch 引入 C# API 项目。我想利用现有的 API 模型作为搜索文档,其中许多模型允许添加自定义数据点。这些是使用JObject https://www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_Linq_JObject.htm来自 Json.NET 的类型。例如:

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 类型的问题。有没有相对简单的解决办法?

以下是我正在权衡的一些选择:

  1. Use 自定义序列化 https://www.elastic.co/guide/en/elasticsearch/client/net-api/current/custom-serialization.html。我开始走这条路,感觉比应有的要复杂得多,而且我从来没有让它发挥作用。

  2. Map JObjects to Dictionary<string, object>s。我已经验证了这个工作原理,但是如果存在嵌套对象(可能存在),我需要通过递归来增强它。而且,理想情况下,我希望它能够与更通用的JToken https://www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_Linq_JToken.htm类型。这是我倾向于的选择,但同样,它感觉比应有的更复杂。

  3. Use the “低级”客户端 https://www.elastic.co/guide/en/elasticsearch/client/net-api/current/elasticsearch-net.html甚至原始 HTTP 调用。诚然,我还没有探索过这一点,但如果它真的比其他选择更简单/更干净,我对此持开放态度。

  4. 将此报告为错误。无论如何,我可能都会这么做。我只是有预感should与...一起工作JObject or any JToken开箱即用,除非有某种原因表明这是预期的行为。


这是 NEST 6.x 的预期行为。

NEST 使用 Json.NET 进行序列化。然而,在 NEST 6.x 中,这种依赖性通过以下方式在 NEST 程序集中内化:

  • IL 将所有 Json.NET 类型合并到 NEST 程序集中
  • 将 Newtonsoft.Json 中的类型命名为 Nested.Json
  • 标记所有类型internal

有一篇博客文章提供了更多详细信息 https://www.elastic.co/blog/nest-elasticsearch-net-6-0-ga解释这一变化背后的动机。

当涉及到处理 Json.NET 类型时,例如Newtonsoft.Json.Linq.JObject,Json.NET 对这些类型进行了特殊处理以进行序列化/反序列化。使用 NEST 6.x,内部化的 Json.NET 不知道如何特殊处理Newtonsoft.Json.Linq.JObject因为内部化 Json.NET 中的所有类型都已重命名为Nest.Json命名空间。

为了支持 Json.NET 类型,需要连接使用 Json.NET 序列化文档的序列化器。这NEST.JsonNetSerializer努吉特包 https://www.nuget.org/packages/NEST.JsonNetSerializer/的创建就是为了帮助解决这个问题。只需添加对的引用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属性将按预期进行序列化。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在 Elasticsearch NEST 中序列化 JToken 或 JObject 类型的属性? 的相关文章

随机推荐