System.Text.Json 自定义 Conveter

System.Text.Json 自定义 Conveter

Intro

System.Text.Json 作为现在 .NET 默认提供的高性能 JSON 序列化器,对于一些比较特殊类型支持的并不太好,业务需求中总是有各种各样的需要,很多时候就需要用到自定义 Converter ,对于微软新出的 DateOnly/TimeOnly 也是需要自定义 Converter 来支持的

Sample

遇到一个(伪)需求,一个 Id 属性可能是字符串也可能是整型数字,举个栗子,

{"Id": 1, "Name": "Test"}
{"Id": "这是一个 Id", "Name": "Test"}

上面这是两个 JSON,想实现用同一个 Model 来保存结果,应该怎么做呢?

如果 Id 只会是整数或者整数的字符串,那么我们就可以用 int 来表示,System.Text.Json 从 5.0 开始支持解析带引号的数字,也就是数字的字符串形式可以参考:https://github.com/dotnet/runtime/issues/30255,只需要配置 JsonNumberHandling, 在 ASP.NET Core 中默认是启用的,是可以把 "1" 反序列化成一个 int 类型的

但是我们的示例中的 Id 是可能不是数字的,转成数字可能会失败的,所以想要把它当作 string 来处理,最后 model 是这样的

public record TestModel
{public string Id { get; init; } = default!;public string? Name { get; set; }
}

但是如果是上面第一种形式的 JSON 反序列化时会发生错误,异常如下:

b2f3a94189bb3b025db604aeff823eea.png

所以还需要自定义一个 Converter 来支持将数字转换成一个字符串,Converter 实现如下,  属性类型是什么,泛型类型就应该是什么

public class StringOrIntConverter : JsonConverter<string>
{public override string Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options){if (reader.TokenType == JsonTokenType.Number){return reader.GetInt32().ToString();}return reader.GetString();}public override void Write(Utf8JsonWriter writer, string value, JsonSerializerOptions options){writer.WriteStringValue(value);}
}

使用 Converter 的方式有两种,一种是在某个属性上添加 JsonConverter 来使用,另一种是作为全局 Converter 来使用,直接配置 JsonSerializerOptions 中的 Converter

属性使用 Converter 示例:

public record TestModel
{[JsonConverter(typeof(StringOrIntConverter))]public string Id { get; init; } = default!;public string? Name { get; set; }
}

配置 JsonSerializerOptions示例:

JsonSerializer.Deserialize<TestModel>(node.ToJsonString(), new JsonSerializerOptions{Converters ={new StringOrIntConverter()}});

这样我们就可以支持从一个 intstring 的转换了,完整示例如下:

var model = new TestModel
{Id = "123",Name = "456"
};
var jsonString = JsonSerializer.Serialize(model);
WriteLine(jsonString);
var node = JsonNode.Parse(jsonString);
ArgumentNullException.ThrowIfNull(node, nameof(node));
node["Id"] = 123;
var newJsonString = node.ToJsonString();
WriteLine(newJsonString);
var newModel = JsonSerializer.Deserialize<TestModel>(newJsonString);
WriteLine(model == newModel);node["Name"] = 345;
WriteLine(JsonSerializer.Deserialize<TestModel>(node.ToJsonString(), new JsonSerializerOptions
{Converters ={new StringOrIntConverter()}
})?.Name);

输出结果如下:

7edac623000b373a0d06fb35354edb36.png
output

More

可能你会问为什么不直接用 object,如果使用 object 的话,上面的 Equals 判断就要改写了,需要自己重新实现比较逻辑,而用 string 就不需要了 希望上面自定义 Converter 的代码对你有所帮助~

References

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

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

  • https://github.com/dotnet/runtime/pull/39685

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

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

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

相关文章

50张图,带你认识大学各专业

全世界只有3.14 % 的人关注了爆炸吧知识专业选的好每天像高考掐指一算&#xff0c;开学就近在眼前。当初纠结自己是考清华还是北大的那一幕也还是历历在目。不过&#xff0c;最后还是没有选择他们&#xff0c;一是因为北京离家太远&#xff0c;怕自己想家&#xff0c;二是因为他…

通达学院计算机组成原理试卷及答案,2021全国网络工程专业大学排名(5篇)

2018全国网络工程专业大学排名(5篇)高考填报志愿选择专业的话&#xff0c;考生需要了解你选择的专业在全国排名怎么样以及选择学校开设的专业在全国排名怎么样&#xff1f;高考升学网小编带你一起了解关于网络工程开设专业的大学排名。以及网络工程就业前景排名怎么样&#xff…

第一次去四川的广东人是什么下场?

1 第一次去四川的广东人▼2 酒店&#xff1a;好的&#xff0c;下次把床头柜也粘地上▼3 朋友家楼下有一窝乌鸦重点是乌鸦窝是晾衣架做的那么问题来了......它们从哪里偷的那么多衣架&#xff1f;&#xff1f;▼4 没有妈咪编不出来的毛衣▼5 这简直一毛一样▼6 我今天非要…

在java中写出html代码,在java里写html代码

在java里写html代码[2021-02-09 07:31:38] 简介:php去除nbsp的方法&#xff1a;首先创建一个PHP代码示例文件&#xff1b;然后通过“preg_replace("/(\s|\&nbsp\;| |\xc2\xa0)/", " ", strip_tags($val));”方法去除所有nbsp即可。推荐&#xff1a;《…

简单的比较两数大小

#!/bin/bash#testecho "----- 比较两数大小-----";while (true) do{echo -n " 请输入a:";read a;echo -n " 请输入b:";read b;if [ $a -eq $b ]then echo "ab&#xff01;";elif [ $a -lt $b ]then echo "a 小于 b || $a < $b…

大咖来了!今年的 COSCon 主论坛你可以见到这些大咖

“ 点击蓝字 / 关注我们 ”| 作者&#xff1a;COSCon21 组委会| 编辑&#xff1a;王玥敏| 设计&#xff1a;朱亿钦COSCon21 主论坛已经开始了紧锣密鼓的筹备工作&#xff0c;大咖们走进影棚&#xff0c;录制主题演讲。那么在本次主论坛中&#xff0c;你都能见到哪些大咖呢&…

3部世界顶级宇宙纪录片,献给对宇宙万物充满好奇的你

全世界只有3.14 % 的人关注了爆炸吧知识宇宙深邃美丽&#xff0c;是黑夜的荧光&#xff0c;是夏天里冒着凉气的西瓜&#xff0c;总是诱人地勾起一代又一代人探索的欲望。对于宇宙思索与探索&#xff0c;人类的脚步从未停止。正是人类对宇宙的好奇&#xff0c;撑起了人类发展的大…

2014全国计算机二级ms office,2014计算机二级MS Office真题及答案

根据光盘中素材文件夹中“操作题素材”子文件夹中“操作题4.2”中所提供的“迎春花”及其中的图片&#xff0c;制作名为“迎春花”的演示文稿&#xff0c;要求如下&#xff1a;(1)有标题页&#xff0c;有演示主题&#xff0c;制作单位(老年协会)&#xff0c;在第一页上要有艺术…

nginx file not found 错误处理小记

2019独角兽企业重金招聘Python工程师标准>>> 安装完php php-fpm nginx 后访问php出现file not found错误&#xff0c;html就没问题配置文件server 段如下 server {listen 80; server_name 192.168.1.11;root /home/www;location ~ .*\.php${ try_files $uri 404;…

1300多名硕博研究生被清退!全都是活该?真相有时候比表面更让人无奈......

全世界只有3.14 % 的人关注了爆炸吧知识有时真相很像结果近日&#xff0c;西安电子科技大学公布了一份名单&#xff0c;拟清退33名“失联博士”。这些被清退的博士研究生中&#xff0c;最长的就读时间竟然是15年&#xff01;更令人震惊的是&#xff0c;自2019年来&#xff0c;已…

SQL Server数据库同步问题分享[未完,待续](一)

SQL Server数据库同步问题分享[未完&#xff0c;待续](一) SQL Server数据库同步问题分享(二)---操作步骤[未完&#xff0c;待续] SQL Server数据库同步问题分享(三)---创建订阅 合并发布(复制)通常也是从发布数据库对象和数据的报表快照开始。并用触发器跟踪在发布服务器和订…

中国最美街景,带你一次看个够

全世界只有3.14 % 的人关注了爆炸吧知识生活永远比电视剧精彩&#xff0c;真正的美景永远比图片美&#xff01;中国960万平方公里的土地上&#xff0c;拥有无穷无尽的美景&#xff0c;足以将你的眼睛搁在天堂。抛开那些耳熟能详的景区不谈&#xff0c;单单是一些普通街道&#…

[031] 实战:书大师网站开发准备

.NET大牛之路 • 王亮精致码农 • 2021.10.19前面我们花了二十篇左右的文章讲 C# 基础和高级知识点。由于后面要讲的东西还有很多&#xff0c;所以 C# 的内容没办法做到讲得细而全&#xff0c;只能走马观花一扫而过。在后面的内容中如果有遇到 C# 高级知识点&#xff0c;我们再…

依赖Zookeeper生成全局唯一序列号

下面2张图来自&#xff1a;http://www.open-open.com/doc/view/2e0a82e0081d489dace301a2c512053c 关于Zookeeper服务安装&#xff0c;配置&#xff0c;启动, 客户端操作参见&#xff1a;http://aiilive.blog.51cto.com/1925756/1684451 http://aiilive.blog.51cto.com/1925756…

小眼睛有多惨?美颜都懒得救你......

1 眼睛小的人系统一般会自动识别为没睁开▼2 你想笑死我吧&#xff1f;&#xff1f;&#xff1f;▼3 大家都是狗&#xff0c;凭什么&#xff1f;&#xff1f;&#xff1f;▼4 这鱼是怎么跳上来的&#xff1f;▼5 感觉有被冒犯到▼6 这个车贴太可爱了&#xff01;▼7 君子…

软件开发了10年,迷茫了

在新疆做了10年软件开发&#xff0c;从asp开始不断学习&#xff0c;每出现一个新技术自己都会夜以继日的学习&#xff0c;总以为这个技术会是潮流&#xff0c;会持续几年&#xff0c;但结果是不到两年就已经落伍。身边的人慢慢的离开了软件开发队伍&#xff0c;终于2年前自己也…

.NET网站国际化策略

我所在的公司是做SAAS软件&#xff0c;用户群体是面向全球的&#xff0c;因此对应业务系统国际化就是顺理成章的事情。其实国际化重点在于多语言支持&#xff0c;本文就从这方面入手。多语言如上解决方案截图&#xff0c;BQoolCommon.Resource是多语言资源工程&#xff0c;下面…

将数字转化为液晶显示屏的样子

发一个很蛋疼的程序&#xff0c;将一个数字转化为液晶显示屏显示的样子&#xff1a;第一个输入是尺寸&#xff0c;第二输入是要转化的数字&#xff0c;当两个参数都为0的时候结束输入&#xff1a; #include<iostream> using namespace std;struct Print{int size;int num…

史上最强电池!三位诺贝尔奖获奖者研究了大半辈子,却坦言还是没看懂?

全世界只有3.14 % 的人关注了爆炸吧知识手机患了忧郁症电量总剩1%晚上十点半了&#xff0c;还剩10%的电量&#xff0c;等我用完这些电就睡觉..5%了&#xff0c;这个推文看完应该就没电了1%了&#xff0c;算了再看一个&#xff0c;还没关机呢看完了&#xff0c;还是1%&#xff0…

libgdx 学习笔记七 libgdx应用程序生命周期

简介 本章内容描述libGDX 应用程序的结构和怎么根据不同的平台版本使用不同的后台 The Application 做为任意libGDX 工程的主入口点。Application 决定平台的版本和后台图形。Application 接口提供了合适的方法来访问Graphics, Audio, Input and File I/O模块。也提供了跨平台的…