资源站 wordpress,仙游县住房和城乡建设局网站,百度前三推广,做网站的登陆功能System.Text.Json 中的 JsonExtensionDataIntro最近两天在排查我们 API 的一个问题#xff0c;查看源码过程中发现 System.Text.Json 里有一个有意思的 JsonExtensionData在反序列化的时候#xff0c;如果反序列化的 Model 中没有对应的属性信息#xff0c;这些信息就会丢失… System.Text.Json 中的 JsonExtensionDataIntro最近两天在排查我们 API 的一个问题查看源码过程中发现 System.Text.Json 里有一个有意思的 JsonExtensionData在反序列化的时候如果反序列化的 Model 中没有对应的属性信息这些信息就会丢失只会保留 Model 里有的数据而 JsonExtensionData 则可以将这些没有对应属性的信息也保留下来在序列化的时候也会保留下来。Sample直接来看示例吧定义的 Model 如下这里使用了 C# 9 引入的 record 来简化代码public record Person(string Name, int Age);如果我们的 JSON 字符串正好只有这两个属性的话JsonSerializer.Serialize(new{Name Ming,Age 10,});如果是这样的那么也不会有什么问题如果 JSON 字符串会有更多的信息比如JsonSerializer.Serialize(new{Name Ming,Age 10,Title SDE,City Shanghai});可以看到这个 JSON 会有更多的信息会包含 Model 里没有定义的 City 和 Title此时在使用上面的 Model 就会出现信息丢失Title 和 City 的信息就会丢掉了System.Text.Json 提供了一种方式 JsonExtensionData 来保存这些在 Model 里没有定义的属性/字段信息使用 JsonExtensionData 的属性/字段有类型要求需要是以下三种类型之一IDictionarystring, objectIDictionarystring, JsonElementJsonObject(.NET 6 新增支持)于是我们就有了下面的测试 Modelpublic record Person(string Name, int Age);public record Person1(string Name, int Age) : Person(Name, Age)
{[JsonExtensionData]public Dictionarystring, object? Extensions { get; set; } new();
}public record Person2(string Name, int Age) : Person(Name, Age)
{[JsonExtensionData]public Dictionarystring, JsonElement Extensions { get; set; } new(StringComparer.OrdinalIgnoreCase);
}public record Person3(string Name, int Age) : Person(Name, Age)
{[JsonExtensionData]public JsonObject? Extensions { get; set; }
}测试代码如下var p1 JsonSerializer.DeserializePerson1(jsonString);
ArgumentNullException.ThrowIfNull(p1, nameof(p1));
WriteLine(JsonSerializer.Serialize(p1.Extensions));var p2 JsonSerializer.DeserializePerson2(jsonString);
ArgumentNullException.ThrowIfNull(p2, nameof(p2));
WriteLine(JsonSerializer.Serialize(p2.Extensions));var p3 JsonSerializer.DeserializePerson3(jsonString);
ArgumentNullException.ThrowIfNull(p3, nameof(p3));
WriteLine(JsonSerializer.Serialize(p3.Extensions));输出结果如下可以看到使用了 JsonExtensionData 之后多余的信息也会保存下来把 Extensions 打印一下都是一样的结果Extensions 中保存了我们没有匹配到的信息这样我们就可以获取到那些可能会丢失掉的数据了我们可以把整个对象直接打印出来using static System.Console;var p JsonSerializer.DeserializePerson(jsonString);
ArgumentNullException.ThrowIfNull(p, nameof(p));
WriteLine(JsonSerializer.Serialize(p));var p1 JsonSerializer.DeserializePerson1(jsonString);
ArgumentNullException.ThrowIfNull(p1, nameof(p1));
WriteLine(JsonSerializer.Serialize(p1));var p2 JsonSerializer.DeserializePerson2(jsonString);
ArgumentNullException.ThrowIfNull(p2, nameof(p2));
WriteLine(JsonSerializer.Serialize(p2));var p3 JsonSerializer.DeserializePerson3(jsonString);
ArgumentNullException.ThrowIfNull(p3, nameof(p3));
WriteLine(JsonSerializer.Serialize(p3));
WriteLine(new string(-, 20));输出结果如下outputMore借助 JsonExtensionData 我们可以实现一些比较灵活的扩展没有用过的童鞋不妨试一下细心的童鞋可能会发现最后一个输出的结果会有一些不同这是一个 BUG 可以参考 issue: https://github.com/dotnet/runtime/issues/60806上述示例可以在 Github 获取 https://github.com/WeihanLi/SamplesInPractice/blob/master/JsonSample/SystemTextJsonSample/JsonExtensionDataSample.csReferenceshttps://github.com/WeihanLi/SamplesInPractice/blob/master/JsonSample/SystemTextJsonSample/JsonExtensionDataSample.cshttps://docs.microsoft.com/en-us/dotnet/standard/serialization/system-text-json-handle-overflow?WT.mc_idDT-MVP-5004222https://docs.microsoft.com/en-us/dotnet/api/system.text.json.serialization.jsonextensiondataattribute?WT.mc_idDT-MVP-5004222https://github.com/dotnet/runtime/issues/61080