ElasticSearch 中的 RegionInfo 序列化
RegionInfo serializing in ElasticSearch
似乎 RegionInfo
对象在序列化方面有点被遗忘了。 CultureInfo
效果很好,可以序列化为字符串。当试图抛出一个 RegionInfo
对象时,我得到了 RegionInfo
的所有属性的混乱,这些属性无法反序列化,因为没有构造函数可以反向获取所有这些属性。我很乐意将 RegionInfo
序列化和反序列化为字符串,例如 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
这听起来像是我的序列化器部分有误,但我觉得我不太了解,无法弄清楚是哪一部分。谢谢。
我认为这里的问题可能是 Elasticsearch 最初从要索引的文档中推断出 RegionInfo
的 object
数据类型映射,现在正在传递 string
值RegionInfo
。您可能需要删除索引并重新创建,将 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
对象在序列化方面有点被遗忘了。 CultureInfo
效果很好,可以序列化为字符串。当试图抛出一个 RegionInfo
对象时,我得到了 RegionInfo
的所有属性的混乱,这些属性无法反序列化,因为没有构造函数可以反向获取所有这些属性。我很乐意将 RegionInfo
序列化和反序列化为字符串,例如 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
这听起来像是我的序列化器部分有误,但我觉得我不太了解,无法弄清楚是哪一部分。谢谢。
我认为这里的问题可能是 Elasticsearch 最初从要索引的文档中推断出 RegionInfo
的 object
数据类型映射,现在正在传递 string
值RegionInfo
。您可能需要删除索引并重新创建,将 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"
}