System.Text.Json 中的 JsonExtensionData

System.Text.Json 中的 JsonExtensionData

Intro

最近两天在排查我们 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 里没有定义的 CityTitle

此时在使用上面的 Model 就会出现信息丢失,TitleCity 的信息就会丢掉了,System.Text.Json 提供了一种方式 JsonExtensionData  来保存这些在 Model 里没有定义的属性/字段信息

使用 JsonExtensionData 的属性/字段有类型要求,需要是以下三种类型之一:

  • IDictionary<string, object>

  • IDictionary<string, JsonElement>

  • JsonObject(.NET 6 新增支持)

于是我们就有了下面的测试 Model

public record Person(string Name, int Age);public record Person1(string Name, int Age) : Person(Name, Age)
{[JsonExtensionData]public Dictionary<string, object?> Extensions { get; set; } = new();
}public record Person2(string Name, int Age) : Person(Name, Age)
{[JsonExtensionData]public Dictionary<string, 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.Deserialize<Person1>(jsonString);
ArgumentNullException.ThrowIfNull(p1, nameof(p1));
WriteLine(JsonSerializer.Serialize(p1.Extensions));var p2 = JsonSerializer.Deserialize<Person2>(jsonString);
ArgumentNullException.ThrowIfNull(p2, nameof(p2));
WriteLine(JsonSerializer.Serialize(p2.Extensions));var p3 = JsonSerializer.Deserialize<Person3>(jsonString);
ArgumentNullException.ThrowIfNull(p3, nameof(p3));
WriteLine(JsonSerializer.Serialize(p3.Extensions));

输出结果如下:

b917871bd5abf39d12d1705078a3d894.png

可以看到使用了 JsonExtensionData 之后,多余的信息也会保存下来,把 Extensions 打印一下都是一样的结果

Extensions 中保存了我们没有匹配到的信息,这样我们就可以获取到那些可能会丢失掉的数据了

我们可以把整个对象直接打印出来

using static System.Console;var p = JsonSerializer.Deserialize<Person>(jsonString);
ArgumentNullException.ThrowIfNull(p, nameof(p));
WriteLine(JsonSerializer.Serialize(p));var p1 = JsonSerializer.Deserialize<Person1>(jsonString);
ArgumentNullException.ThrowIfNull(p1, nameof(p1));
WriteLine(JsonSerializer.Serialize(p1));var p2 = JsonSerializer.Deserialize<Person2>(jsonString);
ArgumentNullException.ThrowIfNull(p2, nameof(p2));
WriteLine(JsonSerializer.Serialize(p2));var p3 = JsonSerializer.Deserialize<Person3>(jsonString);
ArgumentNullException.ThrowIfNull(p3, nameof(p3));
WriteLine(JsonSerializer.Serialize(p3));
WriteLine(new string('-', 20));

输出结果如下:

3fc5d074ff9fdaf11da710559f300242.png

output

More

借助 JsonExtensionData 我们可以实现一些比较灵活的扩展,没有用过的童鞋不妨试一下

细心的童鞋可能会发现最后一个输出的结果会有一些不同,这是一个 BUG 可以参考 issue: https://github.com/dotnet/runtime/issues/60806

上述示例可以在 Github 获取 https://github.com/WeihanLi/SamplesInPractice/blob/master/JsonSample/SystemTextJsonSample/JsonExtensionDataSample.cs

References

  • https://github.com/WeihanLi/SamplesInPractice/blob/master/JsonSample/SystemTextJsonSample/JsonExtensionDataSample.cs

  • https://docs.microsoft.com/en-us/dotnet/standard/serialization/system-text-json-handle-overflow?WT.mc_id=DT-MVP-5004222

  • https://docs.microsoft.com/en-us/dotnet/api/system.text.json.serialization.jsonextensiondataattribute?WT.mc_id=DT-MVP-5004222

  • https://github.com/dotnet/runtime/issues/61080

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/296164.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

双向链表的删除操作

双向链表的删除操作转载于:https://www.cnblogs.com/LoveFishC/archive/2012/12/20/3845821.html

“中科院博士后当辅警”,网友却吵翻了:家里有矿?

全世界只有3.14 % 的人关注了爆炸吧知识这两天的热搜上有一位小哥哥特别引人关注有人看到了发际线有人看到了书香门第的出身更多人留意到了他的学历和身份香港大学博士、中科院博士后四川公安一名辅警↓↓↓缪元颖&#xff0c;四川省成都市公安局高新区分局的一名辅警&#xff…

用java写的常见排序

/** * @author Think *折半插入排序 */ public class binInsertSort { private static int a[]={22,3,43,11,99,88,34,34,33,22,11,1};public static void main(String[] args) {int []b=binInsertSort(a,0,12);for(int i=0;i<b.length;i++){System.out.print(a[i]+&quo…

浅谈python中的一般方法、静态方法(staticmethod)和类方法(classmethod)

我们先来简单谈谈python类中一般方法、静态方法和类方法的区别。1、类中的一般方法一般方法在定义的时候&#xff0c;需要有表示类实例的参数&#xff08;通常以self表示&#xff0c;例如def foo(self,arg1,arg2……)&#xff09;&#xff0c;一般方法不能通过类名.方法名()来调…

matlab损失函数出现nan,[译]在训练过程中loss出现NaN的原因以及可以采取的方法。...

1.梯度爆炸原因&#xff1a;在学习过程中&#xff0c;梯度变得非常大&#xff0c;使得学习的过程偏离了正常的轨迹。症状&#xff1a;观察输出日志(runtime log)中每次迭代的loss值&#xff0c;你会发现loss随着迭代有明显的增长&#xff0c;最后因为loss值太大以致于不能用浮点…

马的种类(七)

鄂伦春马<?xml:namespace prefix o ns "urn:schemas-microsoft-com:office:office" />鄂伦春马产于大小兴安岭山区。繁殖性能好&#xff0c;在小群自由交配的情况下&#xff0c;有些母马一年产一驹。生长缓慢&#xff0c;6~7岁时才能结束生长发育期。一般在…

OAuth 2.0 的探险之旅

前言OAuth 2.0 全称是 Open Authorization 2.0, 是用于授权(authorization)的行业标准协议。OAuth 2.0 专注于客户端开发人员的简单性&#xff0c;同时为 Web 应用程序、桌面应用程序、移动设备应用等提供了特定的授权流程。它在2012年取代了 OAuth 1.0, 并且 OAuth 2.0 协议不…

SQL 分页查询语句大全即(查找第N到M条记录的方法)

SQL 分页查询语句大全即&#xff08;查找第N到M条记录的方法&#xff09; 第一种方法&#xff0c;我的原创方法 row2 表示分页行数 page1 表示页码 getnumrow*page select * from (select top row * from (select top getnum * from Newslist order by id desc) order by id …

揭开不一样的世界,这5部纪录片绝对不能错过!

纪录片一直都是增长见识又带给你力量的东西&#xff0c;你可能忙于学业、生活、工作而不能行万里路&#xff0c;但至少你还可以看纪录片&#xff0c;从一方屏幕看到整个世界。今天就为大家整理了5部高分纪录片&#xff0c;文末附领取方式&#xff0c;快收下吧~01与摩根弗里曼一…

Linux Free命令与cache和buffer的主要区别

本文是转载的&#xff0c;不知道为啥不能直接转载到51&#xff0c;所以copy了下&#xff0c;原文地址是&#xff1a;http://blog.sina.com.cn/s/blog_7a1285bb0100ziep.html free 命令相对于top 提供了更简洁的查看系统内存使用情况&#xff0c;用来显示内存的使用情况&#xf…

算术几何平均matlab,算术-几何平均数——高斯的发现

“算术-几何平均数”既不是算术平均数&#xff0c;也不是几何平均数&#xff0c;由素有“数学王子”之称的德国数学家高斯首先发现和研究。算术-几何平均数&#xff0c;当然与“算术平均数”和“几何平均数”这两个概念有很深的关系。我们知道&#xff0c;但凡一个数学概念或定…

把nc v6的源码看懂

看懂nc v6的源码&#xff01; 碧桂园全部的正式环境的补丁都在我手里。 2015-11-18 2&#xff1a;33 谢谢两位一起努力的兄弟 谢谢超哥&#xff0c;谢谢祈冰哥&#xff0c;谢谢连老师&#xff0c;陈明大哥&#xff0c;谢谢龙哥&#xff0c;珍玉&#xff0c;谢谢廖生哥&#x…

.NET Core TLS 协议指定被我钻了空子~~~

【导读】此前&#xff0c;测试小伙伴通过工具扫描&#xff0c;平台TLS SSL协议支持TLS v1.1&#xff0c;这不安全&#xff0c;TLS SSL协议至少是v1.2以上才行&#xff0c;想到我们早已将其协议仅支持v1.3&#xff0c;那应该非我们平台问题。近日&#xff0c;第三方合作伙伴再次…

Android之CheckBox复选框控件使用inelayout.xml Xml代码

linelayout.xml Xml代码<?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas.android.com/apk/res/android" android:layout_width"match_parent" android:layout_height&quo…

linux如何挂载U盘

挂u盘之前&#xff0c;运行命令cat /proc/partitions,看看现在系统中有哪些分区。插上u盘以后&#xff0c;再次运行上述命令&#xff0c;看看多出来什么分区&#xff08;通常是sda1&#xff0c;PS由于偶是在虚拟机下装的&#xff0c;所以是sdb1). 1、插入U盘 2、输入 fdisk -…

光通信调制方式MATLAB仿真,基于LED的紫外光通信调制方式研究

赘固中文核心期刊基于&#xff2c;&#xff25;&#xff24;的紫外光通信调制方式研究何攀&#xff0c;李晓毅&#xff0c;侯倩&#xff0c;肖文林(重庆通信学院&#xff0c;重庆&#xff14;&#xff10;&#xff10;&#xff10;&#xff13;&#xff15;)摘要&#xff1a;紫…

frame buffer编程--画点功能和新增字符串代替RGBT

&#xff08;一&#xff09;&#xff1a;写在前面 这一次进行了一个比较大的迭代&#xff0c;在这里我先把相对于上一个版本的改进做一个解释&#xff1a; 1:进一步完善画点&#xff0c;增加了使用字符串代替RGBT值2:实现字符串解析出RGBT值3:增加了画圆的算法4:进一步增强了代…

这篇博士毕业论文致谢句句诛心......

全世界只有3.14 % 的人关注了爆炸吧知识本文来源&#xff1a;学术志综合自小木虫、网络等&#xff0c;作者yechm AUT博士毕业论文感谢信&#xff1a;我出生的时候是一个下雪的深夜&#xff0c;我的父亲在床边生了一堆柴火&#xff0c;我的母亲躺在四周漏风的那间破屋角落的床上…

30分钟通过Kong实现.NET网关

什么是KongOpenrestry是一个基于Nginx与Lua的高性能平台&#xff0c;内部有大量的Lua库。其中ngx_lua_moudule使开发人员能使用Lua脚本调用Nginx模块。Kong是一个Openrestry程序&#xff0c;而Openrestry运行在Nginx上&#xff0c;用Lua扩展了nginx。所以可以认为Kong Openres…

Proxy模式简介和用例

在软件系统中&#xff0c;有些对象有时候由于某些原因&#xff08;比如对象创建开销很大&#xff0c;或者某些操作需要安全控制&#xff0c;或者需要进程外的访问&#xff09;&#xff0c;如果直接访问会给使用者或者系统结构带来很多麻烦&#xff0c;这时可以在客户程序和目标…