浅析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小技巧 2.5 则
Sep 12 Javascript
jQuery fadeTo方法调整图片的透明度使用介绍
May 06 Javascript
jQuery的显示和隐藏方法与css隐藏的样式对比
Oct 18 Javascript
ExtJS的拖拽效果示例
Dec 09 Javascript
JavaScript严格模式详解
Nov 18 Javascript
JavaScript中的跨浏览器事件操作的基本方法整理
May 20 Javascript
简单的JS轮播图代码
Jul 18 Javascript
jQuery图片前后对比插件beforeAfter用法示例【附demo源码下载】
Sep 20 Javascript
jQuery实现简单的抽奖游戏
May 05 jQuery
vue插槽slot的理解和使用方法
Apr 03 Javascript
2019最新21个MySQL高频面试题介绍
Feb 06 Javascript
element中table高度自适应的实现
Oct 21 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
我的论坛源代码(四)
2006/10/09 PHP
一个简单的PHP&amp;MYSQL留言板源码
2020/07/19 PHP
php写的带缓存数据功能的mysqli类
2012/09/06 PHP
PHP分页详细讲解(有实例)
2013/10/30 PHP
php实现把url转换迅雷thunder资源下载地址的方法
2014/11/07 PHP
JavaScript在for循环中绑定事件解决事件参数不同的情况
2014/01/20 Javascript
Extjs 4.x 得到form CheckBox 复选框的值
2014/05/04 Javascript
jquery mobile 移动web(5)
2015/12/20 Javascript
js类式继承与原型式继承详解
2016/04/07 Javascript
Javascript基础_嵌入图像的简单实现
2016/06/14 Javascript
Bootstrap三种表单布局的使用方法
2016/06/21 Javascript
概述jQuery的元素筛选
2016/11/23 Javascript
网站发布后Bootstrap框架引用woff字体无法正常显示的解决方法
2016/11/24 Javascript
canvas绘制表盘时钟
2017/01/23 Javascript
JS排序之冒泡排序详解
2017/04/08 Javascript
Node.js  REPL (交互式解释器)实例详解
2017/08/06 Javascript
js 开发之autocomplete=&quot;off&quot;在chrom中失效的解决办法
2017/09/28 Javascript
微信小程序获取用户openid的实现
2018/12/24 Javascript
webpack4.0+vue2.0利用批处理生成前端单页或多页应用的方法
2019/06/28 Javascript
vue如何在用户要关闭当前网页时弹出提示的实现
2020/05/31 Javascript
详细分析Node.js 模块系统
2020/06/28 Javascript
Vue单文件组件开发实现过程详解
2020/07/30 Javascript
零基础写python爬虫之抓取百度贴吧并存储到本地txt文件改进版
2014/11/06 Python
Python实现身份证号码解析
2015/09/01 Python
Python实现数据可视化看如何监控你的爬虫状态【推荐】
2018/08/10 Python
对Python闭包与延迟绑定的方法详解
2019/01/07 Python
python实现电子产品商店
2019/02/26 Python
python 实现在无序数组中找到中位数方法
2020/03/03 Python
Python‘==‘ 及 ‘is‘相关原理解析
2020/09/05 Python
wordpress添加Html5的表单验证required方法小结
2020/08/18 HTML / CSS
草莓网官网:StrawberryNET
2019/08/21 全球购物
学习方法演讲稿
2014/05/10 职场文书
报到证办理个人委托书
2014/10/06 职场文书
2016年春季运动会通讯稿
2015/11/25 职场文书
导游词之山西关帝庙
2019/11/01 职场文书
sql server偶发出现死锁的解决方法
2022/04/10 SQL Server