【问题标题】:How do I serialize properties of type JToken or JObject in Elasticsearch NEST?如何在 Elasticsearch NEST 中序列化 JToken 或 JObject 类型的属性?
【发布时间】:2018-10-10 23:03:47
【问题描述】:

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

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

  1. 使用custom serialization。我开始走这条路,感觉比它应该的要复杂得多,而且我从来没有让它发挥作用。

  2. JObjects 映射到Dictionary<string, object>s。我已经验证了这项工作,但如果有嵌套对象(可能有),我需要通过递归来增强它。而且,理想情况下,我希望它与更通用的 JToken 类型一起使用。这是我倾向于的选项,但再次感觉它比应有的复杂。

  3. 使用"Low Level" client 甚至是原始HTTP 调用。诚然,我还没有探索过这一点,但如果它真的比其他选择更简单/更干净,我愿意接受。

  4. 将此报告为错误。无论如何,我可能会这样做。我只是预感到这应该JObject 或任何开箱即用的JToken 一起工作,除非出于某种原因这是预期的行为。

【问题讨论】:

    标签: c# elasticsearch json.net nest elasticsearch-net


    【解决方案1】:

    这是 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 解释这一变化背后的动机。

    在处理诸如Newtonsoft.Json.Linq.JObject 之类的 Json.NET 类型时,Json.NET 对这些类型进行了特殊处理以进行序列化/反序列化。在 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 属性的文档将按预期序列化。

    【讨论】:

      猜你喜欢
      • 2020-03-30
      • 1970-01-01
      • 2014-07-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多