Newtonsoft 六个超简单又实用的特性,值得一试 【下篇】

一:讲故事

上一篇介绍的 6 个特性从园子里的反馈来看效果不错,那这一篇就再带来 6 个特性同大家一起欣赏。

二:特性分析

1. 像弱类型语言一样解析 json

大家都知道弱类型的语言有很多,如: nodejs,python,php,它们有一个????????的地方就是处理json,不需要像 强类型语言 那样还要给它配一个类,什么意思呢?就拿下面的 json 说事。


{"DisplayName": "新一代算法模型","CustomerType": 1,"Report": {"TotalCustomerCount": 1000,"TotalTradeCount": 50},"CustomerIDHash": [1,2,3,4,5]
}

这个 json 如果想灌到 C# 中处理,你就得给它定义一个适配的类,就如 初篇 的客户算法模型类,所以这里就有了一个需求,能不能不定义类也可以自由解析上面这串 json 呢???哈哈,当然是可以的, 反序列化成 Dictionary 即可,就拿提取 Report.TotalCustomerCount 和 CustomerIDHash 这两个字段演示一下。

static void Main(string[] args){var json = @"{'DisplayName': '新一代算法模型','CustomerType': 1,'Report': {'TotalCustomerCount': 1000,'TotalTradeCount': 50},'CustomerIDHash': [1,2,3,4,5]}";var dict = JsonConvert.DeserializeObject<Dictionary<object, object>>(json);var report = dict["Report"] as JObject;var totalCustomerCount = report["TotalCustomerCount"];Console.WriteLine($"totalCustomerCount={totalCustomerCount}");var arr = dict["CustomerIDHash"] as JArray;var list = arr.Select(m => m.Value<int>()).ToList();Console.WriteLine($"list={string.Join(",", list)}");}

2. 如何让json中的枚举保持更易读的字符串型

这句话是什么意思呢?默认情况下, SerializeObject 会将 Model 中的 Enum 变成数值型,大家都知道数值型语义性是非常差的,如下代码所示:

static void Main(string[] args){var model = new ThreadModel() { ThreadStateEnum = System.Threading.ThreadState.Running };var json = JsonConvert.SerializeObject(model);Console.WriteLine(json);}class ThreadModel{public System.Threading.ThreadState ThreadStateEnum { get; set; }}

对吧,确实语义特别差,那能不能直接生成 Running 这种字符串形式呢?当然可以了。。。改造如下:

var json = JsonConvert.SerializeObject(model, new StringEnumConverter());

这里可能就有人钻牛角尖了,能不能部分指定让枚举生成 string,其他的生成 int ,没关系,这也难不倒我,哪里使用就用 JsonConverter 标记哪里。。。

static void Main(string[] args){var model = new ThreadModel(){ThreadStateEnum = System.Threading.ThreadState.Running,TaskStatusEnum = TaskStatus.RanToCompletion};var json = JsonConvert.SerializeObject(model);Console.WriteLine(json);}class ThreadModel{public System.Threading.ThreadState ThreadStateEnum { get; set; }[JsonConverter(typeof(StringEnumConverter))]public TaskStatus TaskStatusEnum { get; set; }}

3. 格式化 json 中的时间类型

在 model 转化成 json 的过程中,总少不了 时间类型,为了让时间类型 可读性更高,通常会 格式化为 YYYY年/MM月/dd日 ,那如何实现呢?很简单撒,在 JsonConvert 中也是一个 枚举 帮你搞定。。。

static void Main(string[] args){var json = JsonConvert.SerializeObject(new Order(){OrderTitle = "女装大佬",Created = DateTime.Now}, new JsonSerializerSettings{DateFormatString = "yyyy年/MM月/dd日",});Console.WriteLine(json);}public class Order{public string OrderTitle { get; set; }public DateTime Created { get; set; }}

对了,我记得很早的时候,C# 自带了一个 JavaScriptSerializer, 也是用来进行 model 转 json的,但是它会将 datetime 转成 时间戳,而不是时间字符串形式,如果你因为特殊原因想通过 JsonConvert 将时间生成时间戳的话,也是可以的, 用 DateFormatHandling.MicrosoftDateFormat 枚举指定一下即可,如下:

4. 对一些常用设置进行全局化

在之前所有演示的特性技巧中都是在 JsonConvert 上指定的,也就是说 100 个 JsonConvert 我就要指定 100 次,那有没有类似一次指定,整个进程通用呢?这么强大的 Newtonsoft 早就支持啦, 就拿上面的 Order 举例:

JsonConvert.DefaultSettings = () =>{var settings = new JsonSerializerSettings{Formatting = Formatting.Indented};return settings;};var order = new Order() { OrderTitle = "女装大佬", Created = DateTime.Now };var json1 = JsonConvert.SerializeObject(order);var json2 = JsonConvert.SerializeObject(order);Console.WriteLine(json1);Console.WriteLine(json2);

可以看到,Formatting.Indented 对两串 json 都生效了。

5. 如何保证 json 到 model 的严谨性 及提取 json 未知字段

有时候我们有这样的需求,一旦 json 中出现 model 未知的字段,有两种选择:要么报错,要么提取出未知字段,在 Newtonsoft 中默认的情况是忽略,场景大家可以自己找哈。

  • 未知字段报错

static void Main(string[] args){var json = "{'OrderTitle':'女装大佬', 'Created':'2020/6/23','Memo':'订单备注'}";var order = JsonConvert.DeserializeObject<Order>(json, new JsonSerializerSettings{MissingMemberHandling = MissingMemberHandling.Error});Console.WriteLine(order);}public class Order{public string OrderTitle { get; set; }public DateTime Created { get; set; }public override string ToString(){return $"OrderTitle={OrderTitle}, Created={Created}";}}

  • 提取未知字段

我依稀的记得 WCF 在这种场景下也是使用一个 ExtenstionDataObject 来存储客户端传过来的未知字段,有可能是客户端的 model 已更新,server端还是旧版本,通常在 json 序列化中也会遇到这种情况,在 JsonConvert 中使用 _additionalData 就可以帮你搞定,在 OnDeserialized 这种AOP方法中进行拦截,如下代码:

static void Main(string[] args){var json = "{'OrderTitle':'女装大佬', 'Created':'2020/6/23','Memo':'订单备注'}";var order = JsonConvert.DeserializeObject<Order>(json);Console.WriteLine(order);}public class Order{public string OrderTitle { get; set; }public DateTime Created { get; set; }[JsonExtensionData]private IDictionary<string, JToken> _additionalData;public Order(){_additionalData = new Dictionary<string, JToken>();}[OnDeserialized]private void OnDeserialized(StreamingContext context){var dict = _additionalData;}public override string ToString(){return $"OrderTitle={OrderTitle}, Created={Created}";}}

6. 开启 JsonConvert 详细日志功能

有时候在查阅源码的时候开启日志功能更加有利于理解源码的内部运作,所以这也是一个非常实用的功能,看看如何配置吧。

static void Main(string[] args){var json = "{'OrderTitle':'女装大佬', 'Created':'2020/6/23','Memo':'订单备注'}";MemoryTraceWriter traceWriter = new MemoryTraceWriter();var account = JsonConvert.DeserializeObject<Order>(json, new JsonSerializerSettings{TraceWriter = traceWriter});Console.WriteLine(traceWriter.ToString());}public class Order{public string OrderTitle { get; set; }public DateTime Created { get; set; }public override string ToString(){return $"OrderTitle={OrderTitle}, Created={Created}";}}

三:总结

嘿嘿,这篇 6 个特性就算说完了, 结合上一篇一共 12 个特性,是不是非常简单且实用,后面准备给大家带来一些源码解读吧! 希望本篇对您有帮助,谢谢!

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

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

相关文章

C++实现双栈结构(一个顺序表中使用两个栈)

因为平常栈中push的数据不会太多&#xff0c;为了节约空间&#xff0c;所以可以在一个顺序表中使用两个栈 结构图: 在这里我会留一个空间用来判断栈是否满&#xff01; #include <iostream> using namespace std; typedef int ElemType;class DoubleStack { private:El…

Redis凭啥这么快?只能做缓存?架构师道出了真相(颠覆你的认知)

Redis到底有多快Redis采用的是基于内存的采用的是单进程单线程模型的 KV 数据库&#xff0c;由C语言编写&#xff0c;官方提供的数据是可以达到100000的QPS&#xff08;每秒内查询次数&#xff09;。这个数据不比采用单进程多线程的同样基于内存的 KV 数据库 Memcached 差&…

Java面向对象编程(基础部分)

面向对象编程(基础部分) 类与对象 01&#xff1a; public class ObjectWorkDemo {public static void main(String[] args){Cat cat1 new Cat();cat1.name "Tom";cat1.age 3;cat1.color "white";Cat cat2 new Cat();cat2.name "xiaohua"…

多数组实现链表

指针和对象的实现 对象的多数组表示 #include <iostream>using namespace std; typedef int T; class multiple_array_list { private:int capacity;int **key_array;int *next_array;int *pre_array;int count;int head;int tail; public:multiple_array_list(int cap…

Blazor带我重玩前端(一)

写在前面曾经我和前端朋友聊天的时候&#xff0c;我说我希望有一天可以用C#写前端&#xff0c;不过当时更多的是美好的想象&#xff0c;这一切正变得真实……什么是Blazor我们知道浏览器可以正确解释并执行JavaScript代码&#xff0c;那么浏览器是如何执行C#代码的呢&#xff1…

Java面向对象编程(中级)

面向对象编程(中级) 包 访问修饰符 封装 01: public class Encapsulation01 {public static void main(String[] args){Person person new Person();person.name "Tom";person.setAge(30);person.setSalary(30000);} }class Person {public String name;private…

[Mvp.Blazor] 动态路由与钩子函数

&#xff08;Blazor组件的生命周期函数&#xff09;一直在学习也没有停下脚步&#xff0c;用着脑子还是挺好的&#xff0c;感觉可以更脚踏实地一下。最近偶尔也继续看了看Blazor&#xff0c;毕竟我也开源了一个项目嘛&#xff0c;基本我正式开源的项目都会负责到底&#xff0c;…

算法-找出最近点对问题

最近点对问题 找出平面上一对距离最短的点&#xff0c;时间复杂度 O&#xff08;nlgn&#xff09; using System; using System.Collections.Generic;namespace dataLearn {struct Coordinate{public float x;public float y;public Coordinate(float x,float y){this.x x;t…

算法-二分搜索-找出最大值和最小值

二分搜索问题 找出最大值和最小值 时间复杂度O&#xff08;n&#xff09; using System; using System.Collections.Generic;namespace dataLearn {class Program{static void Main(string[] args){List<int> list new List<int> { 10, 3, 6, 4, 7, 1, 9, 2 };v…

Java面向对象编程(高级)

面向对象编程(高级) 类变量和类方法 01: package ChildDemo;public class Child {private String name;public static int cnt 0;public Child(String name){this.name name;}public void join(){System.out.println(name "join the game");} }//package ChildDe…

.NET Core + Kubernetes:Volume

和 Docker 类似&#xff0c;Kubernetes 中也提供了 Volume 来实现数据卷挂载&#xff0c;但 Kubernetes 中 Volume 是基于 Pod&#xff0c;而不是容器&#xff0c;它可被 Pod 中多个容器共享&#xff0c;另外 Kubernetes 中提供比较丰富的 Volume 类型[1]&#xff0c;如&#…

算法-二分搜索-找出最大值和次大值

二分搜索 <2>找出最大值和第二大值 时间复杂度O&#xff08;n) class Program {static void Main(string[] args){List<int> list new List<int> { 10, 3, 6, 4, 7, 1, 9, 2 };var v getMax(list, 0, list.Count - 1);}static (int, int) getMax(List<…

WPF中的Data Binding调试指南

点击蓝字“大白技术控”关注我哟加个“星标★”&#xff0c;每日良时&#xff0c;好文必达&#xff01;WPF中的Data Binding如何Debug?大家平时做WPF开发&#xff0c;相信用Visual studio的小伙伴比较多。XAML代码曾经在某些特殊版本的Visual Studio中是可以加断点进行调试的&…

算法-连续项的最大和问题(最大子数组问题)三种不同解法

连续项的最大和问题 &#xff08;1&#xff09;暴力求解 时间复杂度 O&#xff08;n^2&#xff09; &#xff08;2&#xff09;分治求解 时间复杂度 O&#xff08;nlogn&#xff09; &#xff08;3&#xff09; 线性求解 时间复杂度 O&#xff08;n&#xff09; C#代码 usin…

.NET 5 尝鲜 - 开源项目TerminalMACS WPF管理端支持.NET 5

点击上方“Dotnet9”添加关注哦聊天界面设计TerminalMACS一个使用 Prism 作为模块化框架、基于多个开源控件库作为UI控件选择、集成开源 UI 界面设计的 .NET 5 WPF 客户端项目。项目名称&#xff1a;TerminalMACS WPF管理端项目开源地址&#xff1a;Github&#xff1a;https://…

算法-排序-插入排序

插入排序 特点&#xff1a;原址排序&#xff0c;比较排序&#xff0c;&#xff08;最坏的情况&#xff09;时间复杂度O&#xff08;n^2&#xff09; #include <iostream>void insertion_sort(int *arr,int start,int end) {for (int i start1; i < end1; i) {int k…

MongoDB via Dotnet Core数据映射详解

用好数据映射&#xff0c;MongoDB via Dotnet Core开发变会成一件超级快乐的事。一、前言MongoDB这几年已经成为NoSQL的头部数据库。由于MongoDB free schema的特性&#xff0c;使得它在互联网应用方面优于常规数据库&#xff0c;成为了相当一部分大厂的主数据选择&#xff1b;…

算法-排序-归并排序

归并排序 特点&#xff1a;非原址排序&#xff0c;比较排序&#xff0c;时间复杂度O&#xff08;nlgn&#xff09; 稳定 // // Created by 许加权 on 2021/6/18. //#include <iostream> void merge_sort(int *arr,int start,int end) {if(start < end){int middle …

FreeSql.Generator命令行代码生成器是如何实现的

目录FreeSql介绍FreeSql.GeneratorRazorEngine.NetCore源码解析FreeSql.ToolsFreeSqlFreeSql 是功能强大的对象关系映射技术(O/RM)&#xff0c;支持 .NETCore 2.1 或 .NETFramework 4.0 或 Xamarin。有一个强大的ORM&#xff0c;也方便我们开发一个代码生成器。一般情况下&…

算法-排序-选择排序

选择排序 特点&#xff1a;原址排序&#xff0c;比较排序&#xff0c;时间复杂度O&#xff08;n^2&#xff09; // // Created by 许加权 on 2021/6/19. //#include <iostream>void selection_sort(int *arr,int start,int end) {for (int i start 1; i < end1; i…