.Net JSON序列化实战教程

在.Net开发中,当前主流的序列化JSON字符串主要有两种方式:JavaScriptSerializer及Json.net(Nuget标识:Newtonsoft.Json)。JavaScriptSerializer是微软官方提供的一种方法,所以如果你用的是asp.net mvc,在Action中如果你返回的语句写的是”return Json(xxx);“,其实你用的就是JavaScriptSerializer方式。现在更多的人选择的是Json.net,因为它为用户提供了更加清晰地使用体验,清晰在哪?本文主要就是带你走进它们的世界。

JavaScriptSerializer与Json.net

序列化

我们先定义一个测试用的简单类--Person:

public class Person  
  {  
      public string Name;  
      public int Age;  
      public Guid TokenId { get; set; }  
      public DateTime RegTime;  
      public Person Child;  
      public Person Friend;  
  }

类中的成员仅用来区分不同的变量类型。我们分别以JavaScriptSerializer和Json.net来序列化:

var person = new Person  
{  
    Age = 28,  
    Name = "李玉宝<yubaolee:>",//故意添加特殊字符  
    RegTime = DateTime.Now,  
    TokenId = Guid.NewGuid(),  
    Child = new Person  
    {  
        Age = 1,  
        Name = "baby",  
        RegTime = DateTime.Now,  
        TokenId = Guid.NewGuid()  
    }  
};  //注意这里面的Friend没有赋值,默认为空  
      
    JavaScriptSerializer serializer = new JavaScriptSerializer();  
    var jsstr = serializer.Serialize(person);                //使用JavaScriptSerializer序列化  
    string newtonstr = JsonConvert.SerializeObject(person);  //使用Json.net序列化

JavaScriptSerializer序列化是先生成一个对象,然后调用它的成员函数Serialize进行序列化;

Json.net直接使用提供的静态成员JsonConvert.SerializeObject进行序列化;

两者使用都比较简单,Json.net调用起来方便那么一丢丢!我们来看一下控制台输出结果:

上面绿色为JavaScriptSerializer的结果,下面黄色背景为Json.net的结果,这里需要注意几个地方:

1、 JavaScriptSerializer序列化后的时间格式:"\/Date(1441813200214)\/" 表示的是1970年1月1日(DateTime的最小值)到date实际表示的日期之差的总毫秒数。通常我们需要把它转成标准的时间格式。可以用下面的方法进行字符串处理:

jsstr = Regex.Replace(jsstr, @"\\/Date\((\d+)\)\\/", match =>  
{  
    DateTime dt = new DateTime(1970, 1, 1);  
    dt = dt.AddMilliseconds(long.Parse(match.Groups[1].Value));  
    dt = dt.ToLocalTime();  
    return dt.ToString("yyyy-MM-dd HH:mm:ss");  
});

处理完成后的效果:

当然,你还可以通过使用继承JavaScriptConverter的方式,下面反序列化中会具体提及到这种方式。

Json.net默认生成的日期也不方便客户端阅读,需要简单的处理一下:

string newtonstr = JsonConvert.SerializeObject(p, Formatting.Indented,  
                new IsoDateTimeConverter() {DateTimeFormat = "yyyy-MM-dd HH:mm:ss"});

2、JavaScriptSerializer序列化会对特殊字符(如<>等)进行编码,比如上面的\u003c \u003e,很多人看到这个的时候,第一感觉就是太扯蛋了,接下来就是各种百度,怎么把这个转成正常的”<>”。实际上你不用做任何操作,这是标准的JS编码方式,前端会自行处理这个问题。比如:

<script type="text/javascript">  
    var str = 'yubaolee <yubaolee>'  
    var str2 = 'yubaolee \u003cyubaolee\u003e';  
    alert(str == str2);  //结果为true  
</script>

从上面两点可以看出,JavaScriptSerializer序列化出来的JSON字符串容易给人造成一些困惑,而Json.net完全没有上面的两种情况处理。所以现在很多人都在用Json.net,但从Html标准的角度上来看,JavaScriptSerializer序列化出来的结果更符合Html的要求。不过为了操作习惯,还是建议使用Json.net。

反序列化

我们分别用两种方式对上面已经成功序列化的两个字符串进行反序列化:

//对JavaScriptSerializer生成的字符串进行反序列化  
//使用JavaScriptSerializer方式  
var jsperson = serializer.Deserialize<Person>(jsstr);  
//使用Json.net方式  
var newtonperson = JsonConvert.DeserializeObject<Person>(jsstr);  
  
//对Json.net生成的字符串进行反序列化  
var jsperson2 = serializer.Deserialize<Person>(newtonstr);  
var newtonperson2 = JsonConvert.DeserializeObject<Person>(newtonstr);

通过运行会发现4个反序列化代码都能正常运行,而不是像以前某些前辈说的,JavaScriptSerializer序列化的串只能用它反序列化,Json.net序列化的串只能用Json.net来反序列化。

上面反序列化的字符串是程序生成的,能正常反序列化不足为奇。但通常我们要反序列化的字符串是客户提交到服务器上面来的串,他们通常是不完整的,或有些还会出现类型不符的情况。比如:

string noChildStr =  
    "{\"Name\":\"李玉宝<yubaolee:>\"," +  
    "\"Age\":28," +  
    "\"RegTime\":\"2015-09-11 00:10:48\"," +  
    "\"Friend\":null}";    
  
var jsperson = new JavaScriptSerializer().Deserialize<Person>(noChildStr);  
var newtonperson = JsonConvert.DeserializeObject<Person>(noChildStr);

注意这个字符串中,没有TokenId,没有Child,而且Friend为null。看一看结果:

两个都很智能嘛!解析的结果全部是我们想要的内容。但如果像下面这样呢?

string noChildStr =  
    "{\"Name\":\"李玉宝<yubaolee:>\"," +  
    "\"Age\":28," +  
    "\"RegTime\":\"2015-09-11 00:10:48\"," +  
    "\"Friend\":null," +  
    "\"TokenId\":null}";  //注意这个TokenId为空

在运行的时候,程序会直接报错。

错误的内容很容易理解,因为我们把一个null赋值给Guid类型,肯定会出错。在实际的项目操作过程中还有可能出现把一个内容为空的字符串传给Datetime类型,把一个数字传给GUID等各种参数传递的问题,关键是我们还要来处理它们,而不能使程序直接报错崩溃。

1、在JavaScriptSerializer中有一个JavaScriptConverter可以来处理这些问题,它是用来实现JSON序列化中自定义类型的处理。比如下面的代码,就是处理把一个null赋值给Guid的情况:

public class PersonJsConverter : JavaScriptConverter  
{  
    public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer)  
    {  
        Person person = new Person();  
  
        object value = null;  
        if (dictionary.TryGetValue("TokenId", out value) && value != null)  
            person.TokenId = (Guid) value;  
        //其他字段略...  
          
        return person;  
    }  
  
    public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)  
    {  
        Dictionary<string, object> dic = new Dictionary<string, object>();  
        var node = obj as Person;  
        if (node == null)  
            return null;  
        if (!string.IsNullOrEmpty(node.Name))  
            dic.Add("Name", node.Name);  
        //其他字段略...  
        return dic;  
    }  
  
    public override IEnumerable<Type> SupportedTypes  
    {  
        get  
        {  
            return new Type[] { typeof(Person) };  
        }  
    }  
}

然后在反序列化之前,我们把这个转换注册到实体对象中,这时再执行,程序就一切正常了:

    JavaScriptSerializer serializer = new JavaScriptSerializer();  
    serializer.RegisterConverters(new JavaScriptConverter[] { new PersonJsConverter(),  });  
      
    var deserialize = serializer.Deserialize<Person>(noChildStr);

2、在使用Json.net时,采用了一种更加优雅的方式来处理这个问题--JsonConverter,它可以单独处理一个指定的类成员变量。这样就不用像上面的JavaScriptConverter一样处理整个类的所有成员。代码如下:

public class GuidConverter : JsonConverter  
{  
    public override bool CanConvert(Type objectType)  
    {  
        return objectType.IsAssignableFrom(typeof(Guid));  
    }  
  
    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)  
    {  
        try  
        {  
            return serializer.Deserialize<Guid>(reader);  
        }  
        catch  
        {  
            //如果传进来的值造成异常,则赋值一个初值  
            return Guid.Empty;  
        }  
    }  
  
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)  
    {  
        serializer.Serialize(writer, value);  
    }  
}

值得注意的是JsonConverter是一个Attribute,所以要在类成员上面添加一个特性:

public class Person  
  {  
      public string Name;  
      public int Age;  
      [JsonConverter(typeof(GuidConverter))]  
      public Guid TokenId { get; set; }  
      public DateTime RegTime;  
      public Person Child;  
      public Person Friend;  
  }

这时,再运行程序时,TokenId就会被赋上一个初始的值。看来在反序列化中,Json.net还是更胜一筹。

性能

这是网上给出来两个的性能比较:

综上,在不考虑系统对第三方控件引用的要求情况下,尽量使用Json.net来进行对象序列化处理。

 
其他常用的序列化方法

说了半天,回顾一下序列化的定义:序列化:将对象转换成字节流的过程,这样就可以轻松将对象保存在磁盘文件或数据库中。

反序列化:序列化的逆过程,就是将字节流转换回原来的对象的过程。

asp.net中序列化与反序列化,及Json序列化反序列化

序列化是将对象状态转换为可保持或可传输的格式的过程,反序列化则过程相反。用于存储和传输数据。

(一)asp.net序列化与反序列化

.net提供多种序列化类

(1)BinaryFormatter 类

名字空间:System.Runtime.Serialization.Formatters.Binary

这个类用于以二进制格式将对象或整个连接对象图形序列化和反序列化

构造器两个:
BinaryFormatter()
BinaryFormatter(ISurrogateSelector, StreamingContext)

介绍它的两个主要方法:

1 Serialize方法

将对象或连接对象图形序列化为给定流

它有两个重载:
Serialize(Stream, Object)
Serialize(Stream, Object,Header[])

类Customer

public class Customer
{
    public int Unid { get; set; }
    public string Name { get; set; }
    public string Call { get; set; }
}

下边通过示例来测试序列化方法Serialize

public void TestSerialize()
{
    Customer customer = new Customer {Unid=1,Name="宋江",Call="89589689" };
    FileStream fs = new FileStream("test.dat", FileMode.Create); 
    BinaryFormatter formatter = new BinaryFormatter();
    try
    {
        formatter.Serialize(fs, customer);
    }
    catch
    { }
    finally
    {
        fs.Close();

  }
}

测试时,这个会抛出异常:类型“SerializeTest.Customer”未标记为可序列化。所以要在Customer类上添加修饰标签

[Serializable]
public class Customer

测试,在bin\debug文件夹中可以看到test.dat文件。

2 Deserialize方法

将流反序列化为对象图形,它也有两个重载

Deserialize(Stream)
Deserialize(Stream, HeaderHandler)

通过示例来测试从流进行反序列化

public void TestDeserialize()
{
    Customer customer = new Customer();
    FileStream fs = new FileStream("test.dat", FileMode.Open);
    BinaryFormatter formatter = new BinaryFormatter();
    customer= formatter.Deserialize(fs) as Customer;
    fs.Close();
    Console.WriteLine(customer.Name);
}

结果输出:宋江

(2)SoapFormatter类

名字空间:System.Runtime.Serialization.Formatters.Soap

以 SOAP 格式将对象或整个连接对象的图形序列化和反序列化。

SOAP就是simple object access protocol的缩写,简单对象传输协议。是一种轻量的,简单的,基于xml的协议。

这个要添加对System.Runtime.Serialization.Formatters.Soap.dll的引用

构造器:

SoapFormatter xx=new  SoapFormatter()
SoapFormatter(ISurrogateSelector, StreamingContext)

主要介绍其中2个方法

1 Serialize方法

Serialize(Stream, Object)
Serialize(Stream, Object, Header[]

public void TestSoapSerialize()
{
    Customer customer = new Customer { Unid = 1, Name = "宋江", Call = "89589689" };
    FileStream fs = new FileStream("soaptest.dat", FileMode.Create);
    SoapFormatter formatter = new SoapFormatter();
    try
    {
        formatter.Serialize(fs, customer);
    }
    catch
    { }
    finally
    {
        fs.Close();
    }
}

打开bin\debug中的soaptest.dat文件,这就是soap格式。

2 Deserialize方法

反序列化soap格式

Deserialize(Stream)
Deserialize(Stream, HeaderHandler)

其它的不多说了。

public void TestSoapDeserialize()
{
    Customer customer = new Customer();
    FileStream fs = new FileStream("soaptest.dat", FileMode.Open);
    SoapFormatter formatter = new SoapFormatter();
    customer = formatter.Deserialize(fs) as Customer;
    fs.Close();
    Console.WriteLine(customer.Name);
}

(3)XmlSerializer类

将对象序列化到 XML 文档中和从 XML 文档中反序列化对象

名字空间:System.Xml.Serialization

构造方法太多,不列举了,可以参考帮助

1 Serialize方法

拿出一个来说:

public void Serialize(XmlWriter xmlWriter,Object o)
public void TestXmlSerialize()
{
    Customer customer = new Customer { Unid = 1, Name = "宋江", Call = "89589689" };
    FileStream fs = new FileStream("xmltest.xml", FileMode.Create);
    XmlSerializer formatter = new XmlSerializer(typeof(Customer));
    formatter.Serialize(fs, customer);
    fs.Close();
}

结果可以到debug\bin里查看。

2 Deserialize方法

public void TestXmlDeserialize()
{
    Customer customer = new Customer();
    FileStream fs = new FileStream("xmltest.xml", FileMode.Open);
    XmlSerializer formatter = new XmlSerializer(typeof(Customer));
    customer = formatter.Deserialize(fs) as Customer;
    fs.Close();
    Console.WriteLine(customer.Name);
}

(二)Json序列化与反序列化

Json序列化和反序列化指的是:对象序列化为JSON,并可用于从 JSON 反序列化对象

在.net 3.5中

名字空间:System.Runtime.Serialization.Json

但程序集是: System.ServiceModel.Web.dll

(1)DataContractJsonSerializer类

构造方法很多。

介绍这个类其中2个方法:

1 WriteObject方法

有好种重载,这里测试一个:

public override void WriteObject(Stream stream,Object graph)

测试:

public void TestJsonSerialize()
{
    Customer customer = new Customer { Unid = 1, Name = "宋江", Call = "89589689" };
    DataContractJsonSerializer ds = new DataContractJsonSerializer(typeof(Customer)); 
    FileStream fs = new FileStream("json.txt", FileMode.Create);
    ds.WriteObject(fs, customer);
    fs.Close();
}

进行Json序列化时,类型不必添加修饰标签

在bin\debug里可以看到json串。

2 ReadObject方法

重载很多。

public override Object ReadObject(Stream stream)

测试:

public void TestJsonDeserialize()
{
    DataContractJsonSerializer ds = 
        new DataContractJsonSerializer(typeof(Customer)); 
    FileStream fs = new FileStream("json.txt", FileMode.Open);
    var cc = ds.ReadObject(fs);
    fs.Close();
}

(2)JavaScriptSerializer类

为启用 AFAX 的应用程序提供序列化和反序列化功能

名字空间:System.Web.Script.Serialization

程序集:System.Web.Extensions(在 System.Web.Extensions.dll 中)

说其中2个方法

1 Serialize方法

Serialize(Object)
Serialize(Object, StringBuilder)

public void TestJsSerialize()
{
    Customer customer = new Customer { Unid = 1, Name = "宋江", Call = "89589689" };
    JavaScriptSerializer js = new JavaScriptSerializer(); 
    Console.WriteLine(js.Serialize(customer));
}

输出串:{"Unid":1,"Name":"宋江","Call":"89589689"}

2 Deserialize方法

public void TestJsDeserialize()
{
    string str = File.ReadAllText("jsjson.txt");
    JavaScriptSerializer js = new JavaScriptSerializer();
    Customer customer = js.Deserialize<Customer>(str); 
    Console.WriteLine(customer.Name);
}

(3)Json.net

名字空间:Newtonsoft.Json

添加Newtonsoft.Json.dll程序集

其中2个方法:

1 SerializeObject方法

public void TestJsonnetSerialize()
{
    Customer customer = new Customer { Unid = 1, Name = "宋江", Call = "89589689" };
    string strJson=JsonConvert.SerializeObject(customer);
    StreamWriter sw = File.CreateText("jsonnet.txt");
    sw.Write(strJson);
    sw.Close();
}

2 DeserializeObject方法

public void TestJsonnetDeserialize()
{
    string str = File.ReadAllText("jsonnet.txt");
    Customer customer = JsonConvert.DeserializeObject<Customer>(str);
    Console.WriteLine(customer.Name);
}

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索net
, string
, 字符串
, 对象
, new
filestream
.net json 反序列化、.net json序列化、asp.net json序列化、vb.net json序列化、asp.net json反序列化,以便于您获取更多的相关知识。

时间: 2024-10-08 13:49:45

.Net JSON序列化实战教程的相关文章

Json.Net系列教程 3.Json.Net序列化和反序列化设置

原文 Json.Net系列教程 3.Json.Net序列化和反序列化设置 上节补充 首先补充一点,Json.Net是支持序列化和反序列化DataTable,DataSet,Entity Framework和NHibernate的.我举例说明DataTable的序列化和反序列化.创建一个DataTable对象,如下: DataTable dt = new DataTable(); DataColumn dcName = new DataColumn("Name"); DataColumn

Backbone实战教程(二)

在Backbone实战教程(一)中我们已经写好了基本页面文件.功能需求以及整体框架.今天我们就正式进入js代码的实现部分. 首先附上Backbone和Underscore官方文档地址,这里才是最佳的学习地方: Backbone:http://backbonejs.org/ Underscore:http://underscorejs.org/ 整个实例我已经做好,大家可以在这里看: Backbone通讯录实例v1.0 定义项目的命名空间 var Contact = { Models: {}, C

Json.Net系列教程 1.Json.Net介绍及实例

原文 Json.Net系列教程 1.Json.Net介绍及实例 本系列教程假设读者已经对Json有一定的了解,关于Json在这里不多说.本系列教程希望能对读者开发涉及到Json的.Net项目有一定的帮 助.本系列教程是根据官方文档资料和自己项目应用汇总而成.如果觉得本系列对你有用,望多多关注.本人还只是个未毕业的学生,水平有限,尽请指正. 一.Json.Net有什么用? Json.Net是一个读写Json效率比较高的.Net框架.Json.Net 使得在.Net环境下使用Json更加简单.通过L

Json序列化之.NET开源类库Newtonsoft.Json的研究

原文:Json序列化之.NET开源类库Newtonsoft.Json的研究 一.Json简介                                                                                                                    JSON(全称为JavaScript Object Notation) 是一种轻量级的数据交换格式.它是基于JavaScript语法标准的一个子集. JSON采用完全独立于语言

Http Post发送json序列请求(json序列化和反序列化)

项目中竟然遇到了这样的问题,要求客户端请求的方式为:参数按照json序列化,然后使用post方式传递给服务器.第一次看到这个东东有点一头雾水,刚开始开发的时候全部使用的get请求方式,因为当时公司不考虑数据安全问题.后来使用了post方式,使用到了session.这下倒好接触了序列化json,然后post方式提交. 首先需要引用谷歌的gson.jar文件,这里面有一些序列化参数的方法,我用到的比较简单直接使用了tojson(类名字);   定义最外层的类PostArgs: public clas

Json.Net系列教程 2.Net类型与JSON的映射关系

原文 Json.Net系列教程 2.Net类型与JSON的映射关系 首先谢谢大家的支持和关注.本章主要介绍.Net类型与JSON是如何映射的.我们知道JSON中类型基本上有三种:值类型,数组和对象.而.Net中的类型比较多.到底它们是如何映射的呢? 总体来讲,Json.Net将.Net中的基本类型(int,float,string等)转换为Json的值,数组和集合转换为Json的数组,其它转换为Json对象. 1.基本类型: 2.复杂类型: 3.注意 3.1数组和集合 如果你自定义了实现了数组和

谷歌被K网站恢复收录实战教程(上)

2年前,我的SEO博客在运营过程中曾换过一次程序,网站更新了大量的内容,文章内容质量可能偏低,出现了一些被谷歌认为不符合搜索体验的情况,导致博客从搜索引擎中消失;又因为工作和一些个人原因,一直没有仔细检查网站出现的问题,时隔一年半,终于有时间处理一下,希望通过此次操作,能恢复SEO博客的在谷歌的正常索引. 针对网站百度和谷歌被K有着不同的解决方法,相对来说谷歌有较完善的反馈渠道,即通过Google网站管理员工具,就可以实现对网站的重新审核.英文SEO这次利用Google网站管理用工具进行提交,并

朱文乐:谷歌被K网站恢复收录实战教程(下)

7月6日写了"谷歌被K网站恢复收录实战教程(上)",这篇是上一篇的延续,也是上篇文章实例操作的结果反馈,没看过的朋友建议先看了上篇,便于理解.上次操作后英文SEO本来打算等待一个周时间后查看结果,没想到今天(7月8日)早上凌晨的时候,谷歌就放出了SEO博客的部分内容,因为还要上班只是粗略的看了下就睡觉去了,当时谷歌放出了10条网页,都是我近几天更新的文章,不过并没有收录首页. 这次谷歌重新收录SEO博客,和我预期的并不完全一样,在上篇文章的结尾我曾预计:"一般1-2周后就会出

SEO搜索中文分词算法原理实战教程

SEO搜索中文分词算法原理实战教程,如果一个人想成为一个合格的SEO人员,那么搜索引擎分词思维是必须掌握的,因为只有掌握了分词思维,你才可以做出搜索引擎喜欢,而且用户也喜欢的网页,虽然在梦想之旅视频教程中有和大家分享过搜索引擎中文分词原理,但没有完全的,系统的用文字版本和图片版本和大家分享,那么顾芳源就带大家如何正确学习SEO搜索分词思维吧. 搜索引擎中文分词原理 首先我们要知道搜索引擎工作原理是把每个网页的内容按词来录入到数据库,比如你的文章标题是:梦想SEO实战培训提供免费SEO教程,那么搜