【问题标题】:RegionInfo serializing in ElasticSearchElasticSearch 中的 RegionInfo 序列化
【发布时间】:2019-06-03 15:07:54
【问题描述】:

似乎RegionInfo 对象在序列化方面有点被遗忘了。 CultureInfo 效果很好,并且可以在字符串之间进行序列化。当试图抛出 RegionInfo 对象时,我得到了无法反序列化的所有 RegionInfo 属性的混乱,因为没有构造函数可以反转所有这些属性。我很想将RegionInfos 序列化和反序列化为字符串,例如CultureInfo,但不能完全弄清楚。

我的尝试:

我创建了一个区域信息转换器

public class RegionInfoConverter : JsonConverter
{
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        serializer.Serialize(writer, ((RegionInfo)value).Name);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        var token = JToken.Load(reader);
        return new RegionInfo(token.ToObject<string>());
    }

    public override bool CanConvert(Type objectType)
    {
        return typeof(RegionInfo) == objectType;
    }
}

我把它塞进了 ConnectionSettings:

var connectionSettings = new ConnectionSettings(pool,
    (builtin, settings) => new JsonNetSerializer(
        builtin,
        settings,
        contractJsonConverters: new JsonConverter[] { new RegionInfoConverter() })
);

但我得到了错误:object mapping for [region] tried to parse field [region] as object, but found a concrete value

这听起来像是我的序列化程序之一是错误的,但我觉得我不太了解它是哪一部分。谢谢。

【问题讨论】:

  • 您使用的是哪个版本的 NEST?
  • @RussCam 我正在使用 6.2.0

标签: elasticsearch json.net nest regioninfo


【解决方案1】:

我认为这里的问题可能是 Elasticsearch 最初从要索引的文档中推断出 RegionInfoobject 数据类型映射,现在正在为 RegionInfo 传递 string 值。您可能需要删除索引并重新创建,将RegionInfo 属性映射为keyword 数据类型。

这是一个工作示例

private static void Main()
{
    var defaultIndex = "my_index";
    var pool = new SingleNodeConnectionPool(new Uri("http://localhost:9200"));

    var settings = new ConnectionSettings(pool, (b, s) => 
        new JsonNetSerializer(b, s, contractJsonConverters: new JsonConverter[] { new RegionInfoConverter() })
        )
        .DefaultIndex(defaultIndex);

    var client = new ElasticClient(settings);

    if (client.IndexExists(defaultIndex).Exists)
        client.DeleteIndex(defaultIndex);

    var createIndexResponse = client.CreateIndex(defaultIndex, c => c
        .Settings(s => s
            .NumberOfShards(1)
            .NumberOfReplicas(0)
        )
        .Mappings(m => m
            .Map<MyEntity>(mm => mm
                .AutoMap()
                .Properties(p => p
                    .Keyword(k => k
                        .Name(n => n.RegionInfo)
                    )
                )
            )
        )
    );

    var indexResponse = client.Index(new MyEntity 
    {
        RegionInfo = RegionInfo.CurrentRegion
    }, i => i.Refresh(Refresh.WaitFor));
}

public class MyEntity
{
    public RegionInfo RegionInfo { get; set; }
}

public class RegionInfoConverter : JsonConverter
{
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        if (value == null)
        {
            writer.WriteNull();
            return;
        }

        writer.WriteValue(((RegionInfo)value).Name);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        if (reader.TokenType == JsonToken.Null)
            return null;

        if (reader.TokenType != JsonToken.String)
            throw new JsonSerializationException($"Cannot deserialize {nameof(RegionInfo)} from {reader.TokenType}");

        return new RegionInfo((string)reader.Value);
    }

    public override bool CanConvert(Type objectType)
    {
        return typeof(RegionInfo) == objectType;
    }
}

索引请求发送以下 JSON

{
  "regionInfo": "AU"
}

【讨论】:

  • 最后我决定完全不使用RegionInfo。它还有很多其他的序列化和转换问题。我决定只在一个字符串进入我的系统时对其进行验证,并称之为好。这也使 ES 的东西变得更容易了。不过,了解 ES 数据类型是件好事。很高兴知道。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-04
  • 1970-01-01
  • 1970-01-01
  • 2022-08-04
  • 2019-05-20
  • 1970-01-01
相关资源
最近更新 更多