浅析JavaScriptSerializer类的序列化与反序列化


Posted in Javascript onNovember 22, 2016

JavaScriptSerializer 类由异步通信层内部使用,用于序列化和反序列化在浏览器和 Web 服务器之间传递的数据。说白了就是能够直接将一个C#对象传送到前台页面成为javascript对象。要添加System.Web.Extensions.dll的引用。该类位于System.Web.Script.Serialization命名空间下。

一、属性

MaxJsonLength 获取或设置 JavaScriptSerializer 类接受的 JSON 字符串的最大长度。
RecursionLimit 获取或设置用于约束要处理的对象级别的数目的限制。

二、方法

ConvertToType<(Of <(T>)>) 将给定对象转换为指定类型。
Deserialize<(Of <(T>)>) 将指定的 JSON 字符串转换为 T 类型的对象。
DeserializeObject 将指定的 JSON 字符串转换为对象图。
RegisterConverters 使用 JavaScriptSerializer 实例注册自定义转换器。
Serialize 已重载。 将对象转换为 JSON 字符串。

 给个示例,主要就是了解了一下Serialize与Deserialize两个方法,控制器代码:

public class HomeController : Controller
 {
  public ActionResult Index()
  {
   return View();
  }

  public ActionResult GetJson()
  {
   JavaScriptSerializer jss = new JavaScriptSerializer();
   Person p = new Person(1, "张飞", 20);
   string json = jss.Serialize(p); //序列化成JSON
   Person p1 = jss.Deserialize<Person>(json); //再反序列化为Person对象 注意此方法要求目标类有无参构造函数
   //return Json(json, "text/json");  //很好用,但是返回的终归是字符串,返回到前台要解析一下才能变成javascript对象。
   return Json(new { Id = p1.Id, Name = p1.Name, Age = p1.Age }, "text/json");//如果这样写,返回到javascript中是不用再解析的,直接就是javascript对象
  }

 }
 public class Person
 {
  public Person()
  { }
  public Person(int id, string name, int age)
  {
   this.Id = id;
   this.Name = name;
   this.Age = age;
  }
  public int Id { get; set; }
  public string Name { get; set; }
  public int Age { get; set; }
 }

    前台HTML代码:

<html>
<head>
 <title>javascriptSerializer类测试</title>
 <script src="/jQuery.1.8.3.js" type="text/javascript"></script>
 <script type="text/javascript">
  $(function () {
   $(":button").click(function () {
    $.ajax({
     url: "/Home/GetJson",
     dataType: "json",
     type: "post",
     success: function (response) {
//      var data = JSON.parse(response);
//      $("#Id").text(data.Id);
//      $("#Name").text(data.Name);
//      $("#Age").text(data.Age);

      $("#Id").text(response.Id);
      $("#Name").text(response.Name);
      $("#Age").text(response.Age);
     }
    })
   })
  })
 </script>
</head>
<body>
 <ul>
  <li id="Id"></li>
  <li id="Name"></li>
  <li id="Age"></li>
 </ul>
 <input type="button" value="确认" />
</body>
</html>

试下4个基础方法与属性

class Program
 {
  static void Main(string[] args)
  {
   // 方法 
   // RegisterConverters 使用 JavaScriptSerializer 实例注册自定义转换器。 
   //属性
   // RecursionLimit 获取或设置用于约束要处理的对象级别的数目的限制。 

   JavaScriptSerializer jss = new JavaScriptSerializer();
   Console.WriteLine(jss.MaxJsonLength); //默认接受最大的长度是 2097152 这个是接受JSON字符串的最大长度,超长会有什么后果呢?试下
   jss.MaxJsonLength = 1;

   Person p = new Person(1,"关羽",21);
   //string json = jss.Serialize(p);  //将对象序列化成Json字符串 //此处报异常使用 JSON JavaScriptSerializer 进行序列化或反序列化时出错。字符串的长度超过了为 maxJsonLength 属性设置的值。

   jss.MaxJsonLength = 2097152;
   
   //序列化
   string json = jss.Serialize(p); 
   Console.WriteLine(json); //输出 {"Id":1,"Name":"关羽","Age":21}`这就是Json格式了

   //反序列化Deserialize
   Person p2 = jss.Deserialize<Person>("{\"Id\":1,\"Name\":\"关羽\",\"Age\":21}");
   Console.WriteLine(p2.Id + " " + p2.Name + " " + p2.Age); //输出 1 关羽 21
   //Deserialize的非泛型写法
   Person p3 = jss.Deserialize("{\"Id\":1,\"Name\":\"关羽\",\"Age\":21}",typeof(Person)) as Person; //注意这个方法返回的是object类,因此要强制转换成Person类
   Console.WriteLine(p3.Id + " " + p3.Name + " " + p3.Age); //同样输出 1 关羽 21

   object obj = jss.DeserializeObject("{\"Id\":1,\"Name\":\"关羽\",\"Age\":21}"); //将Json字符转换为Object类型
   //Person p4 = obj as Person; //此行代码转为的p4为null
   Person p4 = jss.ConvertToType<Person>(obj);  //尼玛,原来这个方法是这样用的,知道DeserializeObject转换会为null所以另外写一个吗
   Console.WriteLine(p4.Name);  //输出关羽
   //非泛型版本
   Person p5 = jss.ConvertToType(obj,typeof(Person)) as Person;
   Console.WriteLine(p5.Name);  //输出关羽

   Console.ReadKey();
  }
 }

实现自定义转换器

将指定的数据类型序列化为Json。Serialize方法是个递归方法,会递归地序列化对象的属性,因此在序列化一个复杂对象(比如DataTable)时往往会出现“循环引用”的异常,这时候就需要针对复杂类型自定义一个转换器。下面是DataTable的转换器,原理是把DataTable转换成一个字典列表后再序列化:

所有自定义的转换器都要继承于JavaScriptConverter,并实现Serialize、Deserialize方法和SupportedTypes属性,其中SupportedTypes属性用于枚举此转换器支持的类型。

class Program
 {
  static void Main(string[] args)
  {
   DataTable dt = new DataTable();
   dt.Columns.Add("Id");
   dt.Columns.Add("Name");
   dt.Columns.Add("Age");
   dt.Rows.Add(1, "关羽", 21);
   dt.Rows.Add(2, "刘备", 22);
   dt.Rows.Add(3, "张飞", 20);

   JavaScriptSerializer jss = new JavaScriptSerializer();
   //注册转换器的方法,用于复杂转换除了实现还需要注册到JavaScriptSerializer
   jss.RegisterConverters(new JavaScriptConverter[] { new DataTableConverter() });

   string strJson = jss.Serialize(dt);
   Console.WriteLine(strJson);
   //输出 {"Rows":[{"Id":"1","Name":"关羽","Age":"21"},{"Id":"2","Name":"刘备","Age":"22"},{"Id":"3","Name":"张飞","Age":"20"}]}

   Console.ReadKey();
  }
 }

 /// <summary>
 /// DataTable JSON转换类
 /// </summary>
 public class DataTableConverter : JavaScriptConverter
 {
  public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)
  {
   DataTable dt = obj as DataTable;
   Dictionary<string, object> result = new Dictionary<string, object>();

   List<Dictionary<string, object>> rows = new List<Dictionary<string, object>>();

   foreach (DataRow dr in dt.Rows)
   {
    Dictionary<string, object> row = new Dictionary<string, object>();
    foreach (DataColumn dc in dt.Columns)
    {
     row.Add(dc.ColumnName, dr[dc.ColumnName]);
    }
    rows.Add(row);
   }

   result["Rows"] = rows;

   return result;
  }

  public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer)
  {
   throw new NotImplementedException();
  }

  /// <summary>
  /// 获取本转换器支持的类型
  /// </summary>
  public override IEnumerable<Type> SupportedTypes
  {
   get { return new Type[] { typeof(DataTable) }; }
  }
 }

限制序列化的层次

class Program
 {
  static void Main(string[] args)
  {
   JavaScriptSerializer jss = new JavaScriptSerializer();
   Console.WriteLine(jss.RecursionLimit); //默认的序列化层次是100

   Person p1 = new Person(1, "刘备", 24);
   p1.p = new Person(2, "关羽", 23);
   p1.p.p = new Person(3, "张飞", 21);

   string strJson = jss.Serialize(p1);
   Console.WriteLine(strJson);
   //输出 {"Id":1,"Name":"刘备","Age":24,"p":{"Id":2,"Name":"关羽","Age":23,"p":{"Id":3,"Name":"张飞","Age":21,"p":null}}}

   //现在将层次减少到1
   jss.RecursionLimit = 1;
   string strJson2 = jss.Serialize(p1);//这行代码是报异常的,显示已超出 RecursionLimit。 这就是这个属性的作用
   
   //最后再来说一个特性,比如如果我有某一个属性不希望它序列化,那么可以设置添加
   
   Console.ReadKey();
  }
 }

 public class Person
 {
  public Person()
  { }

  public Person(int id, string name, int age)
  {
   this.Id = id;
   this.Name = name;
   this.Age = age;
  }

  public int Id { get; set; } 
  public string Name { get; set; } 
  public int Age { get; set; } 
  //里面嵌套一个Person
  public Person p { get; set; }
 }

    [ScriptIgnore]禁止某属性序列化

class Program
 {
  static void Main(string[] args)
  {
   JavaScriptSerializer jss = new JavaScriptSerializer();
   Person p = new Person(1,"刘备",24);
   Console.WriteLine(jss.Serialize(p));
   File.WriteAllText(@"D:\123.txt", jss.Serialize(p)); //输出 {"Id":1,"Age":24}
   Console.ReadKey();
  }
 }

 public class Person
 {
  public Person()
  { }

  public Person(int id, string name, int age)
  {
   this.Id = id;
   this.Name = name;
   this.Age = age;
  }

  public int Id { get; set; } 
  [ScriptIgnore]
  public string Name { get; set; } 
  public int Age { get; set; }
 }

以上就是本文的全部内容,希望对大家有所帮助,谢谢对三水点靠木的支持!

Javascript 相关文章推荐
javascript getElementsByClassName函数
Apr 01 Javascript
window.parent与window.openner区别介绍
Apr 12 Javascript
js判断一个字符串是否包含一个子串的方法
Jan 26 Javascript
属于你的jQuery提示框(Tip)插件
Jan 20 Javascript
jquery trigger函数执行两次的解决方法
Feb 29 Javascript
最基础的vue.js双向绑定操作
Aug 23 Javascript
js与jQuery实现获取table中的数据并拼成json字符串操作示例
Jul 12 jQuery
video.js 实现视频只能后退不能快进的思路详解
Aug 09 Javascript
node使用Mongoose类库实现简单的增删改查
Nov 08 Javascript
Vue中props的详解
May 16 Javascript
如何使用CSS3和JQuery easing 插件制作绚丽菜单
Jun 18 jQuery
JS实现盒子拖拽效果
Feb 06 Javascript
JS如何设置iOS中微信浏览器的title
Nov 22 #Javascript
原生JS查找元素的方法(推荐)
Nov 22 #Javascript
自己封装的一个原生JS拖动方法(推荐)
Nov 22 #Javascript
SelecT下拉框选中和取值的解决方法
Nov 22 #Javascript
javascript入门之window对象【新手必看】
Nov 22 #Javascript
AngularJS实现DOM元素的显示与隐藏功能
Nov 22 #Javascript
JavaScript ES6中CLASS的使用详解
Nov 22 #Javascript
You might like
php图片处理:加水印、缩略图的实现(自定义函数:watermark、thumbnail)
2010/12/02 PHP
8个PHP程序员常用的功能汇总
2014/12/18 PHP
PHP模板引擎Smarty内置变量调解器用法详解
2016/04/11 PHP
PHP实现微信退款的方法示例
2019/03/26 PHP
使用PHPWord生成word文档的方法详解
2019/06/06 PHP
Ext面向对象开发实践(续)
2008/11/18 Javascript
javascript闭包的高级使用方法实例
2013/07/04 Javascript
JavaScript 数组详解
2013/10/10 Javascript
JS+CSS实现仿新浪微博搜索框的方法
2015/02/24 Javascript
JavaScript编程中window的location与history对象详解
2015/10/26 Javascript
JS实现网页右侧带动画效果的伸缩窗口代码
2015/10/29 Javascript
javascript实现五星评分功能
2015/11/10 Javascript
原生JavaScript实现滚动条效果
2020/03/24 Javascript
几种二级联动案例(jQuery\Array\Ajax php)
2016/08/13 Javascript
javaScript 事件绑定、事件冒泡、事件捕获和事件执行顺序整理总结
2016/10/10 Javascript
jQuery制作全屏宽度固定高度轮播图(实例讲解)
2017/07/08 jQuery
js学习心得_一个简单的动画库封装tween.js
2017/07/14 Javascript
浅谈Vue-cli单文件组件引入less,sass,css样式的不同方法
2018/03/13 Javascript
实例详解BootStrap的动态模态框及静态模态框
2018/08/13 Javascript
微信小程序wx.request的简单封装
2019/11/13 Javascript
Python实现利用163邮箱远程关电脑脚本
2018/02/22 Python
pycharm安装和首次使用教程
2018/08/27 Python
Django开发的简易留言板案例详解
2018/12/04 Python
深度辨析Python的eval()与exec()的方法
2019/03/26 Python
手动安装python3.6的操作过程详解
2020/01/13 Python
Python3以GitHub为例来实现模拟登录和爬取的实例讲解
2020/07/30 Python
PyTorch 中的傅里叶卷积实现示例
2020/12/11 Python
如何开发安全的AJAX应用
2014/03/26 面试题
精细化工应届生求职信
2013/11/17 职场文书
国际贸易专业个人求职信范文分享
2013/12/14 职场文书
付款委托书范本
2014/04/04 职场文书
社区平安建设方案
2014/05/25 职场文书
2014年医院个人工作总结
2014/12/09 职场文书
2015年教研组工作总结
2015/05/04 职场文书
捐款仪式主持词
2015/07/04 职场文书
比较node.js和Deno
2021/04/27 Javascript