NewtonSoft JsonConverter在ASP中不启动.. NET Core 3.1与Elasticsearc



我正在使用从Elasticsearch数据库检索数据的Web API。数据库是由一个完全不同的软件填充的,我无法修改。数据中的一个字段metatag.description应该使用单个值填充,但有时由于上游数据中的错误而最终使用值数组。(我也不能修改这些,这是一个大约200个网站的集合。)

不一致的数据结构以前是通过向模型的相关成员添加自定义JsonConverter来处理的。

从ASP更新项目后。. NET Core 2.1到3.1,当对象从Elasticsearch反序列化时,自定义JsonConverter不再被调用。

项目文件引用Microsoft.AspNetCore.Mvc.NewtonsoftJson包。

<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="3.1.*" />

Newtonsoft。Json在ConfigureServices()中初始化:

services.AddControllers().AddNewtonsoftJson();

模型的精简版本看起来像这样(完整的文件包括using Newtonsoft.Json;)。模型有一个单独的Description字段,但有时上游数据源发送一个数组而不是单个值。(我们不能合理地修复上游来源)

public class SiteWideSearchResult
{
[Text(Name = "title")]
public string Title { get; set; }
[Text(Name = "metatag.description")]
[JsonConverter(typeof(MetadataDescriptionConverter))]
public string Description { get; set; }
}

JsonConverter当前看起来是这样的,但是这些行都没有被执行,设置时也没有到达任何断点(这个完整的文件还包括using Newtonsoft.Json;):

public class MetadataDescriptionConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
throw new NotImplementedException();
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
throw new NotImplementedException();
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
如上所述,有两个版本的结构被反序列化。JsonConverter意味着处理这两种数据,并允许在模型中存储(可能更改的)数据版本。

因为它匹配模型,这个版本正确地反序列化:

{
"_index": "myindex",
"_type": "doc",
"_id": "item_id_1",
"_score": 4.3536105,
"_source": {
"metatag.description": "Single description entry",
"title": "This structure works"
}
}

这个版本应该由自定义的JsonConverter来处理。事实上,它失败了。

{
"_index": "myindex",
"_type": "doc",
"_id": "item_id_2",
"_score": 4.3536105,
"_source": {
"metatag.description": [
"First description line",
"Second description line"
],
"title": "This structure fails"
}
}

第二个结构的错误是expected:'String Begin Token', actual:'[',这是有意义的,但这就是转换器要解决的问题。除了,它没有被调用。

我怀疑System.Text.Json序列化器正在被使用,而不是Newtonsoft.Json的序列化器。

这个答案似乎表明在ConfigureServicesusing语句中添加Newtonsoft是不够的。然而,答案的简洁让我不清楚需要改变什么(我认为是Razor标记)。我没有发现任何文档建议类似的webapi(可能这是一个属性?这是我已经在使用的)。

我尝试过的事情

  • 如所写,模型和转换器确实与。net 2.1一起工作,但我突然想到,新版本的Nest中的反序列化器可能会停止,因为Description[Text]装饰。我试过把它改成[Nested],但是没有成功。

  • 全部删除映射属性,使用[JsonProperty(PropertyName = "metatag.description", ItemConverter = typeof(MetadataDescriptionConverter))]。没有区别。

  • 在整个SiteWideSearchResult模型上使用JsonConverter属性,但这也不执行转换器。(它也不会碰到转换器中的任何断点。)

. NET核心从Newtonsoft.JSON到原生System.Text.Json.Serialization的变化是转移注意力。

真正的罪魁祸首是版本7的变化。Elasticsearch的NEST客户端。从7.0版本开始,NEST不再使用Newtonsoft。Json在内部.

对于从Elasticsearch检索数据时反序列化的特定情况,正确的方法似乎是指定一个自定义序列化器,如该页所述。

对于我的特定用例,解决方案是通过在调用ConnectionSettings构造函数时添加sourceSerializer: JsonNetSerializer.Default来使用JsonNetSerializer。

var connectionSettings =
new ConnectionSettings(pool, sourceSerializer: JsonNetSerializer.Default);
var client = new ElasticClient(connectionSettings);

另一方面,如果自定义映射的需求扩展到索引创建时,则自定义的"访问者模式映射"可能更合适。

相关内容

  • 没有找到相关文章

最新更新