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,一经查实,立即删除!

相关文章

jwt的token自动续约_JWT(JSON Web Token)自动延长到期时间

cchamberlain..6如果您使用的是节点(React/Redux/Universal JS),则可以安装npm i -S jwt-autorefresh.此库根据用户计算的访问令牌到期之前的秒数(基于令牌中编码的exp声明)计划刷新JWT令牌.它有一个广泛的测试套件,可以检查很多条件,以确保任何奇怪的活动都伴随着有关环境配置…

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

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

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

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

diff和patch工具使用(转)

本文转自 http://blog.chinaunix.net/uid-22848040-id-1767554.html diff和patch是一对工具&#xff0c;在数学上来说&#xff0c;diff是对两个集合的差运算&#xff0c;patch是对两个集合的和运算。 diff比较两个文件或文件集合的差异&#xff0c;并记录下来&#xff0c;生成…

自动布局

以前iOS 布局UI界面的经常编写大量的坐标计算代码为了保证在3.5 4.0屏幕上都有完美UI界面效果 有时需要分别为2中屏幕编写不同坐标计算代码(屏幕适配)Autolayout是一种自动布局 自ios7 Autolayout效率增加Autolayout功能比Autoresizing强大很多 黄色 控件的frame不匹配所添加的…

ant 执行多个构建文件

如果需要在一个构件文件中通过Ant命令去执行另一个Ant项目&#xff0c;或者说要执行本项目的子项目的构件文件。这时Ant这个核心任务就派上用场了。简单地说Ant任务的作用就相当于在命令行通过Ant命令执行构件文件。值得注意的是Ant任务依赖于target元素&#xff0c;需要在某个…

rockmq运维指令_RocketMQ 运维指令

1.1.控制台使用RocketMQ 提供有控制台及一系列控制台命令&#xff0c;用于管理员对主题&#xff0c;集群&#xff0c;broker 等信息的管理登录控制台首先进入RocketMQ 工程&#xff0c;进入/RocketMQ/bin在该目录下有个mqadmin 脚本查看帮助在mqadmin 下可以查看有哪些命令sh m…

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

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

我的C++开发工具链

工欲善其事&#xff0c;必先利其器。想要干好活&#xff0c;顺手的工具是必不可少的。来分享下我的C开发工具链。 平台&#xff1a;Windows 编译器&#xff1a;MSVC IDE&#xff1a;Visual Studio 版本控制&#xff1a;TortoiseGit 静态检查&#xff1a;VisualStudio_Scan 内存…

为什么 Dapper 的批量插入比我预期的要慢很多?

咨询区 kenwarner&#xff1a;我的项目中有一个批量插入的需求&#xff0c;我采用的是 Dapper 连接数据库&#xff0c;下面是我的代码。var members new List<Member>(); for (int i 0; i < 50000; i) {members.Add(new Member(){Username i.toString(),IsActive …

在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;《…

append()与extend()

list函数append与extend的区别&#xff1a;前者的参数可以是任何类型&#xff0c;把元素加入到list中&#xff1b;后者的参数必须是list类型&#xff0c;把它和原list合并。 >>> a [1, 2, 3] >>> a.append([4, 5]) >>> a [1, 2, 3, [4, 5]] >&g…

简单的比较两数大小

#!/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;撑起了人类发展的大…

mysql如何查询某条记录在分页的第几页_分页插件的使用

mybatis中首先要在配置文件中配置一些东西&#xff0c;配置sqlaMapconfig和mapper.xml,然后根据这些配置去创建一个会话工厂&#xff0c;再根据会话工厂创建会话&#xff0c;会话发出操作数据库的sql语句(作用是操作数据库)&#xff0c;然后通过执行器操作数据&#xff0c;再使…

DataAdapter.FillSchema 方法

备忘: http://msdn.microsoft.com/zh-cn/library/229sz0y5.aspx转载于:https://www.cnblogs.com/lindj0307/archive/2012/08/28/2660298.html

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

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

routine tortoisesvn operations-1

接下来, 我们讲一下tortoisesvn的常规操作. update, revert和switch的区别, 这三个命令的图标都是从服务器端到客户端的箭头, 容易搞混.1. update是最常用的操作, 就是用来更新本地的work copy, 当然, 如果某个文档是基于svn server的最新版本做了修改,那么update并不会从svn s…

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;…