一:讲故事

上一篇介绍的 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.TotalCustomerCountCustomerIDHash 这两个字段演示一下。


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 个特性,是不是非常简单且实用,后面准备给大家带来一些源码解读吧! 希望本篇对您有帮助,谢谢!

如您有更多问题与我互动,扫描下方进来吧~

Newtonsoft 六个超简单又实用的特性,值得一试 【下篇】的更多相关文章

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

    一:讲故事 看完官方文档,阅读了一些 Newtonsoft 源码,对它有了新的认识,先总结 六个超经典又实用的特性,同大家一起分享,废话不多说,快来一起看看吧~~~ 二:特性分析 1. 代码格式化 如 ...

  2. ASP.NET中一种超简单的Ajax解决方案

    为什么是Ajax2? 因为之前有一个blqw.Ajax,并且已经在项目中投入使用了,但是没有这个方便,这个是后来才弄的,为了纪念第一版的blqw.Ajax,所以这个就2了... 话说看了评论才发现,原 ...

  3. 超简单的全新win10安装

    1.准备工作! 这里说一下需要装系统的东西: 至少8G的U盘或内存卡 一台Windows电脑 在要安装的电脑上至少有16G的空间,最好至少64G. 2.现成电脑下载文件(已经有重装系统U盘跳过这一步) ...

  4. 分享六个基于Bootstrap的实用开发教程和模板演示

    关于Bootstrap,相信大家一定不陌生,它已经成为现在主流产业的一个重要工具,Bootstrap提供了优雅的HTML和CSS规范,它基于jQuery框架开发的,它在jQuery框架的基础上进行了更 ...

  5. 【Android自己定义View实战】之自己定义超简单SearchView搜索框

    [Android自己定义View实战]之自己定义超简单SearchView搜索框 这篇文章是对之前文章的翻新,至于为什么我要又一次改动这篇文章?原因例如以下 1.有人举报我抄袭,原文链接:http:/ ...

  6. 【转载】手把手教你使用Git(简单,实用)

    手把手教你使用Git(简单,实用) 标签: git 2016年04月21日 20:51:45 1328人阅读 评论(0) 收藏 举报 一:Git是什么? Git是目前世界上最先进的分布式版本控制系统. ...

  7. 超简单集成 HMS ML Kit 实现最大脸微笑抓拍

    前言 如果大家对 HMS ML Kit 人脸检测功能有所了解,相信已经动手调用我们提供的接口编写自己的 APP 啦.目前就有小伙伴在调用接口的过程中反馈,不太清楚 HMS ML Kit 文档中的 ML ...

  8. 把C#程序(含多个Dll)合并成一个Exe的超简单方法

    开发程序的时候经常会引用一些第三方的DLL,然后编译生成的exe文件就不能脱离这些DLL独立运行了. 但是,很多时候我们本想开发一款只需要一个exe就能完美运行的小工具.那该怎么办呢? 下文介绍一种超 ...

  9. 记住密码超简单实现(C#)

    实现效果如下 实现过程 [Serializable] class User { //记住密码 private string loginID; public string LoginID { get { ...

随机推荐

  1. 创建多线程的方式&Thread类的常用方法

    创建多线程的第一种方式:继承java.lang.Thread类 注意:1.一个线程只能执行一次start() 2.不能通过Thread实现类对象的 run()去启动一个线程 3.增加加一个线程,需要新 ...

  2. 小谢第8问:ui框架的css样式如何更改

    目前有三种方法, 1.使用scss,增加样式覆盖,但是此种方法要求css的className需要与框架内的元素相一致,因此修改时候需要特别注意,一个父级的不同就可能修改失败 2.deep穿透,这种方法 ...

  3. 前端开发SEO的理解

    所谓seo(Search Engine Optimization)即搜索引擎优化.简单说就是百度.谷歌搜索引擎的‘蜘蛛’,如下图: 搜索引擎蜘蛛是通过,连接地址来找到你的网站的,seo就是让你的网站符 ...

  4. PAT1065 单身狗 (25分) 思路记录——参考大神柳婼

    1065 单身狗 (25分)   “单身狗”是中文对于单身人士的一种爱称.本题请你从上万人的大型派对中找出落单的客人,以便给予特殊关爱. 输入格式: 输入第一行给出一个正整数 N(≤ 50 000), ...

  5. dell5460笔记本电脑ubuntu18.04系统音频驱动的安装和使用

    一.背景: 近期使用dell5460笔记本在ubuntu系统下观看视频,发现没有声音,考虑安装音频驱动. 二.音频驱动的安装 linux系统的音频驱动基于ALSA(即Advanced Linux So ...

  6. Rocket - tilelink - fastProperty

    https://mp.weixin.qq.com/s/9nikweQUGG5FO3Z8t6feaw 介绍Parameters中定义的fastProperty的实现.(使用最近的新版本,差别不大)   ...

  7. js实现浏览器打印功能

    最近接触到一个新需求,实现打印机打印小票的功能.打的一桌子小票(惭愧),不过也基本满足了业务上的需求,现在分享一下如何实现(好记性不如烂笔头) 先上代码 // 布局代码 <div id=&quo ...

  8. Java实现 蓝桥杯 基础练习 特殊的数字

    基础练习 特殊的数字 时间限制:1.0s 内存限制:512.0MB 提交此题 锦囊1 锦囊2 问题描述 153是一个非常特殊的数,它等于它的每位数字的立方和,即153=111+555+333.编程求所 ...

  9. Java实现 LeetCode 566 重塑矩阵(遍历矩阵)

    566. 重塑矩阵 在MATLAB中,有一个非常有用的函数 reshape,它可以将一个矩阵重塑为另一个大小不同的新矩阵,但保留其原始数据. 给出一个由二维数组表示的矩阵,以及两个正整数r和c,分别表 ...

  10. Java实现 LeetCode 300 最长上升子序列

    300. 最长上升子序列 给定一个无序的整数数组,找到其中最长上升子序列的长度. 示例: 输入: [10,9,2,5,3,7,101,18] 输出: 4 解释: 最长的上升子序列是 [2,3,7,10 ...