【问题标题】:What is the most dirt simple way to override one specific type for NEST serialization覆盖 NEST 序列化的一种特定类型的最简单的方法是什么
【发布时间】:2022-01-08 20:20:55
【问题描述】:

我有一个复杂的文档,它在各种不同的子键中都有一个自定义日期字段,即:

var doc = new Document
{
    MyCustomDateTime StartTime
    Matches = new []
    {
        MyCustomDateTime StartTime
        MyCustomDateTime EndTime
    }
}

不使用属性属性,因为这种类型是从 dll 中提取的,我可以覆盖MyCustomDateTime 类型的序列化和反序列化的最简单方法是什么。

我正在寻找类似的东西,或者扩展默认的序列化器类来处理一种额外的类型:

settings.DefaultSerializerFor<MyCustomDateTime>(d => MyConverter.ToString(d), d => MyConverter.FromString(d));

或类似:

public class MyCustomSerializer : DefaultElasticSearchSerializer
{
     public string OnSerialize(object member)
     {
          if (member is MyCustomDateTime) { return MyConverter.ToString(d); }
          return base.OnSerialize(member);
     }
     ...
}

现在,它似乎只发布对象的公共属性。不幸的是,对于这个特定的类,这不是我正在寻找的行为。

【问题讨论】:

    标签: c# elasticsearch serialization nest


    【解决方案1】:

    实现自定义序列化的最简单方法是

    1. 连接JsonNetSerializer
    2. 为您的类型定义转换器
    3. 向 JsonNetSerializer 注册它

    一个例子

    private static void Main()
    {
        var defaultIndex = "default_index";
        var pool = new SingleNodeConnectionPool(new Uri($"http://localhost:9200"));
        var settings = new ConnectionSettings(
            pool, 
            (builtin, settings) => new JsonNetSerializer(builtin, settings, contractJsonConverters: new List<JsonConverter>
        {
            new MyCustomDateTimeConverter()
        }))
            .DefaultIndex(defaultIndex);
            
        var client = new ElasticClient(settings);
            
        var indexResponse = client.Index(
            new MyDocument {
                Message = "message",
                CustomDateTime = new MyCustomDateTime 
                { 
                    Custom = new DateTimeOffset(2022,1,9,14,0,0,0, TimeSpan.FromHours(10)) 
                }
            }, i => i.Id(1));
    }
    
    public class MyCustomDateTime 
    {
        public DateTimeOffset Custom { get; set; }
    }
    
    public class MyCustomDateTimeConverter : JsonConverter<MyCustomDateTime>
    {
        public override void WriteJson(JsonWriter writer, MyCustomDateTime value, JsonSerializer serializer)
        {
            writer.WriteValue(value.Custom);
        }
    
        public override MyCustomDateTime ReadJson(JsonReader reader, Type objectType, MyCustomDateTime existingValue, bool hasExistingValue, JsonSerializer serializer)
        {
            var dateTime = reader.ReadAsDateTimeOffset();
            return dateTime is null ? null : new MyCustomDateTime { Custom = dateTime.Value };
        }
    }
    
    public class MyDocument
    {
        public string Message {get;set;}    
        public MyCustomDateTime CustomDateTime {get;set;}
    }
    

    产量

    PUT http://localhost:9200/default_index/_doc/1?pretty=true
    {
      "message": "message",
      "customDateTime": "2022-01-09T14:00:00+10:00"
    }
    

    【讨论】:

    • 切换到 JsonSerializer 是否会对性能产生巨大影响?我读到他们实现的内部 Utf8Json 更快/性能更高。我担心影响
    • 这是自定义序列化的唯一选择,因为 Utf8Json 序列化都是内部的。由于需要将读取和写入流传递给 JSON.Net 序列化程序,因此存在性能开销,但了解实际影响的唯一方法是使用您的文档和使用情况来衡量它。实现自定义序列化程序的另一种方法是将更简单的 POCO 映射为不需要自定义序列化的 Elasticsearch 文档类型。这可能更可取,因为它会使将来升级到 NEST 8.x 更容易,这很可能使用 System.Text.Json。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-02-22
    • 2010-09-25
    • 2016-01-29
    • 2018-07-07
    • 1970-01-01
    • 2015-09-10
    • 1970-01-01
    相关资源
    最近更新 更多