c# Newtonsoft 六个值得使用的特性(下)

 更新时间:2020年11月3日 15:20  点击:2257

一:讲故事

上一篇介绍的 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);

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

以上就是c# Newtonsoft 六个值得使用的特性(下)的详细内容,更多关于c# Newtonsoft 特性的资料请关注猪先飞其它相关文章!

[!--infotagslink--]

相关文章

  • C#实现简单的登录界面

    我们在使用C#做项目的时候,基本上都需要制作登录界面,那么今天我们就来一步步看看,如果简单的实现登录界面呢,本文给出2个例子,由简入难,希望大家能够喜欢。...2020-06-25
  • 浅谈C# 字段和属性

    这篇文章主要介绍了C# 字段和属性的的相关资料,文中示例代码非常详细,供大家参考和学习,感兴趣的朋友可以了解下...2020-11-03
  • C#中截取字符串的的基本方法详解

    这篇文章主要介绍了C#中截取字符串的的基本方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-11-03
  • C#实现简单的Http请求实例

    这篇文章主要介绍了C#实现简单的Http请求的方法,以实例形式较为详细的分析了C#实现Http请求的具体方法,需要的朋友可以参考下...2020-06-25
  • C#连接SQL数据库和查询数据功能的操作技巧

    本文给大家分享C#连接SQL数据库和查询数据功能的操作技巧,本文通过图文并茂的形式给大家介绍的非常详细,需要的朋友参考下吧...2021-05-17
  • C#中new的几种用法详解

    本文主要介绍了C#中new的几种用法,具有很好的参考价值,下面跟着小编一起来看下吧...2020-06-25
  • 使用Visual Studio2019创建C#项目(窗体应用程序、控制台应用程序、Web应用程序)

    这篇文章主要介绍了使用Visual Studio2019创建C#项目(窗体应用程序、控制台应用程序、Web应用程序),小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2020-06-25
  • C#开发Windows窗体应用程序的简单操作步骤

    这篇文章主要介绍了C#开发Windows窗体应用程序的简单操作步骤,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-04-12
  • C#从数据库读取图片并保存的两种方法

    这篇文章主要介绍了C#从数据库读取图片并保存的方法,帮助大家更好的理解和使用c#,感兴趣的朋友可以了解下...2021-01-16
  • C#和JavaScript实现交互的方法

    最近做一个小项目不可避免的需要前端脚本与后台进行交互。由于是在asp.net中实现,故问题演化成asp.net中jiavascript与后台c#如何进行交互。...2020-06-25
  • C++调用C#的DLL程序实现方法

    本文通过例子,讲述了C++调用C#的DLL程序的方法,作出了以下总结,下面就让我们一起来学习吧。...2020-06-25
  • 轻松学习C#的基础入门

    轻松学习C#的基础入门,了解C#最基本的知识点,C#是一种简洁的,类型安全的一种完全面向对象的开发语言,是Microsoft专门基于.NET Framework平台开发的而量身定做的高级程序设计语言,需要的朋友可以参考下...2020-06-25
  • C#变量命名规则小结

    本文主要介绍了C#变量命名规则小结,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-09-09
  • C#绘制曲线图的方法

    这篇文章主要介绍了C#绘制曲线图的方法,以完整实例形式较为详细的分析了C#进行曲线绘制的具体步骤与相关技巧,具有一定参考借鉴价值,需要的朋友可以参考下...2020-06-25
  • C# 中如何取绝对值函数

    本文主要介绍了C# 中取绝对值的函数。具有很好的参考价值。下面跟着小编一起来看下吧...2020-06-25
  • c#自带缓存使用方法 c#移除清理缓存

    这篇文章主要介绍了c#自带缓存使用方法,包括获取数据缓存、设置数据缓存、移除指定数据缓存等方法,需要的朋友可以参考下...2020-06-25
  • c#中(&&,||)与(&,|)的区别详解

    这篇文章主要介绍了c#中(&&,||)与(&,|)的区别详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-06-25
  • 经典实例讲解C#递归算法

    这篇文章主要用实例讲解C#递归算法的概念以及用法,文中代码非常详细,帮助大家更好的参考和学习,感兴趣的朋友可以了解下...2020-06-25
  • C#学习笔记- 随机函数Random()的用法详解

    下面小编就为大家带来一篇C#学习笔记- 随机函数Random()的用法详解。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2020-06-25
  • C#中list用法实例

    这篇文章主要介绍了C#中list用法,结合实例形式分析了C#中list排序、运算、转换等常见操作技巧,具有一定参考借鉴价值,需要的朋友可以参考下...2020-06-25