如何在Elasticsearch NEST中序列化JToken或JObject类型的属性? [英] How do I serialize properties of type JToken or JObject in Elasticsearch NEST?

查看:88
本文介绍了如何在Elasticsearch NEST中序列化JToken或JObject类型的属性?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm introducing Elasticsearch into a C# API project. I'd like to leverage existing API models as search documents, many of which allow for adding custom data points. These are implemented using the JObject type from Json.NET. For example:

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

这允许用户发送这样的JSON请求正文,效果很好:

This allows users to send JSON request bodies like this, which works great:

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

但是,如果我在NEST中将此类型用作文档类型,则这些额外的属性将以某种方式丢失其值,并序列化为:

However, if I use this as a document type in NEST, those extra properties are losing their values somehow, serializing as:

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

ExtraProps 添加 [Nest.Object] 属性不会改变行为.据我了解,NEST在内部使用Json.NET,因此我不希望它在Json.NET类型方面出现问题.有一个相对简单的解决方法吗?

Adding a [Nest.Object] attribute to ExtraProps didn't change the behavior. As I understand it, NEST uses Json.NET internally, so I wouldn't expect it to have problems with Json.NET types. Is there a relatively simple fix for this?

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

Here are some options I'm weighing:

  1. 使用自定义序列化.我沿着这条路走了,感觉变得比应该的要复杂得多,但我从未成功过.

  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.

JObject s映射到 Dictionary< string,object> s.我已经验证了此方法的有效性,但是如果有嵌套对象(可能存在),则需要通过递归来增强它.并且,理想情况下,我希望它与更通用的 JToken 类型.这是我倾向于的选项,但同样,它感觉比应有的要复杂.

Map JObjects to 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. This is the option I'm leaning toward, but again, it feels more complicated than it should be.

使用低级"客户端,甚至是原始HTTP调用.诚然,我还没有对此进行探讨,但是如果它真的比其他方法更简单/更干净,我会接受的.

Use the "Low Level" client or even raw HTTP calls. Admittedly I haven't explored this, but if it's really simpler/cleaner than the alternatives, I'm open to it.

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

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.

推荐答案

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

This is expected behaviour with NEST 6.x.

NEST使用Json.NET进行序列化.但是,在NEST 6.x中,

NEST uses Json.NET for serialization. In NEST 6.x however, this dependency was internalized within the NEST assembly by

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

有一篇博客文章,提供了更多详细信息解释发生这种变化的动机.

There's a blog post with further details explaining the motivations behind this change.

在处理诸如 Newtonsoft.Json.Linq.JObject 之类的Json.NET类型时,Json.NET对于这些类型的序列化/反序列化具有特殊的处理方式.使用NEST 6.x,内部化的Json.NET不知道如何专门处理 Newtonsoft.Json.Linq.JObject ,因为内部化的Json.NET中的所有类型都已重命名为 Nest.Json 命名空间.

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. 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.

要支持Json.NET类型,需要连接使用Json.NET序列化您的文档的序列化程序.创建了 NEST.JsonNetSerializer nuget包这.只需在项目中添加对 NEST.JsonNetSerializer 的引用,然后按如下所示连接序列化器

To support Json.NET types, a serializer that uses Json.NET to serialize your documents needs to be hooked up. The NEST.JsonNetSerializer nuget package was created to help with this. Simply add a reference to NEST.JsonNetSerializer to your project, then hook up the serializer as follows

// 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 属性的文档将按预期进行序列化.

With this is place, documents with JObject properties will be serialized as expected.

这篇关于如何在Elasticsearch NEST中序列化JToken或JObject类型的属性?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆