简体   繁体   English

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

[英]How do I serialize properties of type JToken or JObject in Elasticsearch NEST?

I'm introducing Elasticsearch into a C# API project. 我正在将Elasticsearch引入C#API项目。 I'd like to leverage existing API models as search documents, many of which allow for adding custom data points. 我想利用现有的API模型作为搜索文档,其中许多模型允许添加自定义数据点。 These are implemented using the JObject type from Json.NET. 这些是使用Json.NET中的JObject类型实现的。 For example: 例如:

public class Product
{
    public int Id { get; set; }
    public string Name { get; set; }
    public JObject ExtraProps { get; set; }
}

This allows users to send JSON request bodies like this, which works great: 这允许用户发送像这样的JSON请求体,这很好用:

{
   "Id": 123,
   "Name": "Thing",
   "ExtraProps": {
      "Color": "red",
      "Size": "large"
   }
}

However, if I use this as a document type in NEST, those extra properties are losing their values somehow, serializing as: 但是,如果我在NEST中将其用作文档类型,那些额外的属性会以某种方式丢失其值,序列化为:

{
   "Id": 123,
   "Name": "Thing",
   "ExtraProps": {
      "Color": [],
      "Size": []
   }
}

Adding a [Nest.Object] attribute to ExtraProps didn't change the behavior. 添加[Nest.Object]属性ExtraProps没有改变行为。 As I understand it, NEST uses Json.NET internally, so I wouldn't expect it to have problems with Json.NET types. 据我了解,NEST在内部使用Json.NET,所以我不希望它有Json.NET类型的问题。 Is there a relatively simple fix for this? 对此有一个相对简单的解决方案吗?

Here are some options I'm weighing: 以下是我正在权衡的一些选项:

  1. Use custom serialization . 使用自定义序列化 I started down this path, it got to feeling way more complicated than it should be, and I never did get it working. 我开始沿着这条路走下去,感觉比现在更复杂,我从来没有让它发挥作用。

  2. Map JObject s to Dictionary<string, object> s. JObject映射到Dictionary<string, object> s。 I have verified this works, but if there are nested objects (which there could be), I'll need to enhance it with recursion. 我已经验证了这个工作,但是如果有嵌套对象(可能存在),我需要通过递归来增强它。 And, ideally, I'd like this to work with the more general JToken type. 而且,理想情况下,我希望使用更通用的JToken类型。 This is the option I'm leaning toward, but again, it feels more complicated than it should be. 这是我倾向于的选择,但同样,它感觉比它应该更复杂。

  3. Use the "Low Level" client or even raw HTTP calls. 使用“低级”客户端甚至原始HTTP调用。 Admittedly I haven't explored this, but if it's really simpler/cleaner than the alternatives, I'm open to it. 诚然,我没有探索过这个,但如果它比替代品更简单/更清洁,我会对它持开放态度。

  4. Report this as a bug. 将此报告为错误。 I'll probably do this regardless. 无论如何,我可能会这样做。 I just have a hunch this should work with JObject or any JToken out of the box, unless there is some reason that this is intended behavior. 我只是预感到这应该JObject或任何JToken开箱即用,除非有某种原因这是预期的行为。

This is expected behaviour with NEST 6.x. 这是NEST 6.x的预期行为。

NEST uses Json.NET for serialization. NEST使用Json.NET进行序列化。 In NEST 6.x however, this dependency was internalized within the NEST assembly by 然而,在NEST 6.x中,这种依赖性在NEST程序集内部被内化

  • IL-merging all Json.NET types into the NEST assembly IL将所有Json.NET类型合并到NEST程序集中
  • renamespacing the types within Newtonsoft.Json to Nest.Json 将Newtonsoft.Json中的类型重命名为Nest.Json
  • marking all types internal 标记internal所有类型

There's a blog post with further details explaining the motivations behind this change. 有一篇博客文章,详细解释了这一变化背后的动机。

When it comes to handling Json.NET types such as Newtonsoft.Json.Linq.JObject , Json.NET has special handling for these types for serialization/deserialization. 在处理Json.NET类型(如Newtonsoft.Json.Linq.JObject ,Json.NET对这些类型进行了特殊处理,以进行序列化/反序列化。 With NEST 6.x, the internalized Json.NET does not know how to specially handle Newtonsoft.Json.Linq.JObject because all types within the internalized Json.NET have been renamespaced to the Nest.Json namespace. 使用NEST 6.x,内化的Json.NET不知道如何专门处理Newtonsoft.Json.Linq.JObject因为内部化的Json.NET中的所有类型都已Nest.Json命名为Nest.Json命名空间。

To support Json.NET types, a serializer that uses Json.NET to serialize your documents needs to be hooked up. 要支持Json.NET类型,需要连接使用Json.NET来序列化文档的序列化程序。 The NEST.JsonNetSerializer nuget package was created to help with this. 创建NEST.JsonNetSerializer nuget包是为了帮助解决这个问题。 Simply add a reference to NEST.JsonNetSerializer to your project, then hook up the serializer as follows 只需在项目中添加对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);

With this is place, documents with JObject properties will be serialized as expected. 有了这个地方,具有JObject属性的文档JObject预期序列化。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM