1.为什么序列化
我们单方面的只把对象转成字节数组还不行,因为没有规则的字节数组我们是没办法把对象的本来面目还原回来的,所以我们必须在把对象转成字节数组的时候就制定一种规则(序列化),那么我们从IO流里面读出数据的时候再以这种规则把对象还原回来(反序列化)。
定义:序列化是指将对象转换成字节序列的过程,反序列化则是将字节序列恢复为对象的过程
作用:由于计算机数据存储和传输都是二进制数据,所以将对象序列化后可以实现该对象在网络上的传输和在硬盘上的存储.
2.如何(反)序列化
关于序列化,就不得不提开源类库:Newtonsoft.Json,它提供了强大的序列功能,拥有稳定的性能.下面的这些例子就需要引用Newtonsoft.Json类库.
工作中常用序列化DataTable、DataSet、Entity,三个使用方法都相似,这里以DataSet为例介绍
2.1 Newtonsoft.Json的序列化简单处理
public partial class WebForm1 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
DataTable dt1 = new DataTable("Old");
dt1.Columns.AddRange(new DataColumn[] {
new DataColumn("Name",typeof(string)),
new DataColumn { ColumnName="Age",DataType=typeof(int)},
new DataColumn { ColumnName = "MenPai", DataType = typeof(string) }
} );
dt1.Rows.Add(new object[] { "周伯通", 38, "重阳宫" });
dt1.Rows.Add(new object[] { "欧阳锋", 49, "白驼山" });
dt1.Rows.Add(new object[] { "洪七公", 52, "丐帮" });
dt1.Rows.Add(new object[] { "黄药师", 55, "桃花岛" });
DataTable dt2 = dt1.Clone();
dt2.TableName="New";//克隆表的结构,包括架构和约束
dt2.Rows.Add(new object[] { "郭靖", 22, "丐帮" });
dt2.Rows.Add(new object[] { "黄蓉", 19, "丐帮" });
dt2.Rows.Add(new object[] { "杨康", 49, "金" });
DataSet ds = new DataSet("JiangHu");
ds.Tables.AddRange(new DataTable[] { dt1, dt2 });
//序列化
string s = JsonConvert.SerializeObject(ds);//序列化成了Json字符串
//反序列化
DataSet newDs = JsonConvert.DeserializeObject<DataSet>(s);
foreach(DataTable dt in newDs.Tables)
{
Console.Write(dt.TableName + "\n"); // "\n"表示回车
foreach(DataRow dr in dt.Rows)
{
foreach(DataColumn dc in dt.Columns)
{
Console.Write(dc.ColumnName + ":" + dr[dc] + " ");
}
Console.Write("\n");
}
}
}
}
2.2 Newtonsoft.Json的序列化特殊处理
A.设置序列化模式
序列化模式有两种:OptOut:除外模式、OptIn:包含模式。
A1 OptOut:除外模式
需要给类标记[JsonObject(MemberSerialization.OptOut)],给类成员标记[JsonIgnore]
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
List<Character> characters = new List<Character>() {
new Character{Id=1,Name="TangSan",Age=16,WuHun="LanYinCao+HaoTianChui",School="SLK"},
new Character{Id=2,Name="XiaoWu",Age=15,WuHun="MeiGuTu",School="SLK"},
new Character{Id=3,Name="NingRongRong",Age=15,WuHun="JiuBaoLiuLi",School="SLK"},
};
string s = JsonConvert.SerializeObject(characters);
Console.WriteLine(s);
Console.ReadKey();
}
}
[JsonObject(MemberSerialization.OptOut)]
public class Character
{
[JsonIgnore]
public int Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
public string WuHun { get; set; }
public string School { get; set; }
}
}
A2 OptIn:包含模式
需要给类标记[JsonObject(MemberSerialization.OptIn)],给类成员标记[JsonProperty] ,由于和A1例子相似此处就不举例子了。
B.处理非公有成员
Newtonsoft.Json可以支持 序列化私有成员
处理方法:只需要在私有成员上面加标识[“JsonProperty”],就可以了。比 如:
[JsonProperty]
private string WuHun { get; set; }
C.自定义成员名
我们在序列化时,不想使用属性或字段的名字,可以完成改名。
改名在属性上加如下标记,即可,比如
[JsonProperty(PropertyName = “武魂”)]
public string WuHun { get; set; }
D.动态成员清单
对于不同的序列化,我们需要的属性或字段如果不同,还可以通过清单来动态完成。
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
List<Character> characters = new List<Character>() {
new Character{Id=1,Name="TangSan",Age=16,WuHun="LanYinCao+HaoTianChui",School="SLK"},
new Character{Id=2,Name="XiaoWu",Age=15,WuHun="MeiGuTu",School="SLK"},
new Character{Id=3,Name="NingRongRong",Age=15,WuHun="JiuBaoLiuLi",School="SLK"},
};
JsonSerializerSettings jsetting = new JsonSerializerSettings();
var propertiesList = new string[] { "Name", "Age", "WuHun" };
jsetting.ContractResolver = new MyPropsContractResolver(propertiesList);
string s = JsonConvert.SerializeObject(characters, Formatting.Indented, jsetting);
Console.WriteLine(s);
Console.ReadKey();
}
}
public class Character
{
public int Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
public string WuHun { get; set; }
public string School { get; set; }
}
/// <summary>
/// 动态成员
/// </summary>
public class MyPropsContractResolver : DefaultContractResolver
{
string[] props = null;
public MyPropsContractResolver(string[] props)
{
//属性的清单
this.props = props;
}
//重写创建要序列化的属性
protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
{ //JsonProperty:将JSON属性映射到.net成员或构造函数参数。
IList<JsonProperty> list = base.CreateProperties(type, memberSerialization);
//只保留清单有列出的属性
return list.Where(p => props.Contains(p.PropertyName)).ToList();//此处涉及到linq知识,请自行学习
}
}
}
E.日期处理:
对于日期处理也是这套类库比较强大的地方,提供了转换类IsoDateTimeConverter来完成对日期的处理。
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using System;
using System.Collections.Generic;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
List<Character> characters = new List<Character>() {
new Character{Id=1,Name="TangSan",Age=16,WuHun="LanYinCao+HaoTianChui",School="SLK",Birthday=DateTime.Now},
new Character{Id=2,Name="XiaoWu",Age=15,WuHun="MeiGuTu",School="SLK",Birthday=DateTime.Now},
new Character{Id=3,Name="NingRongRong",Age=15,WuHun="JiuBaoLiuLi",School="SLK",Birthday=DateTime.Now},
};
string s = JsonConvert.SerializeObject(characters, Formatting.Indented);//Formatting.Indented会自动对字符串进行格式化,使其更易阅读
Console.WriteLine(s);
Console.ReadKey();
}
}
public class Character
{
public int Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
public string WuHun { get; set; }
public string School { get; set; }
[JsonConverter(typeof(MyDateTimeConverter))]
public DateTime Birthday { get; set; }
}
public class MyDateTimeConverter : DateTimeConverterBase
{
private static IsoDateTimeConverter dtConverter = new IsoDateTimeConverter { DateTimeFormat = "yyyy-MM-dd hh-mm-ss" };
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
return dtConverter.ReadJson(reader, objectType, existingValue, serializer);
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
dtConverter.WriteJson(writer, value, serializer);
}
}
public class MyCnDateTimeConverter : DateTimeConverterBase
{
private static IsoDateTimeConverter dtConverter = new IsoDateTimeConverter { DateTimeFormat = "yyyy年MM月d日 hh时mm分ss秒" };
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
return dtConverter.ReadJson(reader, objectType, existingValue, serializer);
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
dtConverter.WriteJson(writer, value, serializer);
}
}
}
Newtonsoft.Json的功能远不止这些
比如 Newtonsoft.Json.Linq 提供了使用Linq查询JSON的很多方法,希望小伙伴闲暇慢慢控究。
更加详细的使用,可以参考官方网站的示例有100多个,还有详细的API文档
URL:http://www.newtonsoft.com/json/help/html/SerializationSettings.htm
当然还有二进制流、xml、soap、json序列化和反序列化,这些序列化是否需要引用类库或者使用微软自带类库,这些还需要自己探索。在这个过程中重要的是需要对各种序列化方法的了解与熟悉,这方面可以参照爱整理
序列化知识拓展
.NET Framework 几种序列化技术,严格来说只有两种,就是二进制序列化,和使用数据格式协定的序列化(包含 XML,SOAP.JSON 等)
XML 序列化 仅序列化公共属性和字段,且不保持类型保真度。
二进制序列化保持类型保真度,用于在应用程序的不同调用之间保留对象的状态。
Json序列化 B/S
移动开发方向,全称JavaScript Object Notation(JavaScript对象表示法)是一种轻量级的数据交换方式。