学习之路十一:JSON(序列化与反序列化)
最近公司项目中用到了Json操作,从.NET后台读取数据,通过Json转化在传给“Andiron”端呈现,于是通过几天的学习,对它有了一点的理解!
1.Json的理解
Json其实就是一个序列化和反序列化的操作,而通过序列化操作之后的数据可以跨平台使用,这就促使了可以使用两个平台,一个做后台,一个做前台,数据访问层通过Json来传递!
2.可以序列化的标志
1 [Serializable]
2 public class MyPeople
3 {
4 public string Name { get; set; }
5
6 public string FatherName { get; set; }
7 }
从上面代码可以看出要通过添加[Serializable]特性来标志这个对象是可以序列化的!
[NonSerialized] 特性,如果在你的属性上面加上这个特性,就表示这个属性将不会被序列化!
3.什么是序列化和可序列化
序列化首先从内存或其它文件中(MemorySteam或FileStream等)中把对象读取出来并通过一定方式进行序列化,最后进行输出!
反序列化首先会通过流操作(MemorySteam或FileStream等)读取传过来的值把它写入内存或文件中,然后通过一定序列化方式转化流对象 → 实体对象!
推荐文章 → [Serializable]在C#中的作用-NET 中的对象序列化
4.使用二进制(BinaryFormatter)进行序列化
4.1序列化
1 MyPeople myPeople = new MyPeople() { Name = "yangcaogui", FatherName = "caoxiaolong" }; 2 IFormatter binaryFormatter = new BinaryFormatter(); 3 using (Stream stream = new FileStream("one.txt", FileMode.Create, FileAccess.Write, FileShare.None)) //也可以使用MemoryStream内存流 4 { 5 binaryFormatter.Serialize(stream, myPeople); 6 stream.Close(); 7 }
4.2反序列化
1 IFormatter binaryFormatter = new BinaryFormatter();
2 using (Stream streamOne = new FileStream("one.txt", FileMode.Open, FileAccess.Read, FileShare.None))
3 {
4 MyPeople myPeopleOne = (MyPeople)binaryFormatter.Deserialize(streamOne);
5 Console.WriteLine(myPeopleOne.Name + "\t" + myPeopleOne.FatherName);
6 }
5.使用SoapFormatter进行序列化
这个跟二进制序列化不一样的地方是 → 最后的数据是以XML的形式存在!
5.1序列化
5.2反序列化
基本代码跟二进制反序列化一样的,就不贴出来了!
6.使用XmlSerializer序列化
它使用的范围比较广,都可以对“DataContract”和“Serializable”标志的对象进行序列化和反序列化的操作!
它可以对一个“XML”的文件进行序列化!
6.1序列化
1 XmlSerializer xmlSerializer = new XmlSerializer(typeof(My));
2 using (MemoryStream memoryStream = new MemoryStream())
3 {
4 xmlSerializer.Serialize(memoryStream, my);
5 Console.WriteLine("\n\n------------------4→XmlSerializer------------------------------------\n\n");
6 Console.WriteLine(Encoding.UTF8.GetString(memoryStream.ToArray()));
7 }
序列化格式如下:
6.2反序列化
1 XmlSerializer xmlSerializer = new XmlSerializer(typeof (My));
2 using (MemoryStream memoryStreamOne = new MemoryStream(Encoding.UTF8.GetBytes(str), 0, str.Length)) // str 是我序列化之后的数据
3 {
4 My myOne = (My) xmlSerializer.Deserialize(memoryStreamOne);
5 Console.WriteLine("----------反序列化的结果------------------");
6 Console.WriteLine(myOne.Name + "\t" + myOne.NameOne);
7 }
7.DataContractSerializer,DataContractJsonSerializer,NetDataContractSerializer
Note:DataContractSerializer 和DataContractJsonSerializer 需要.NET Frameword 3.5才能使用!
首先要序列化和反序列化的对象都要加上序列化的特性!
1 [DataContract] 2 public class My 3 { 4 [DataMember] 5 public string Name { get; set; } 6 7 [DataMember] 8 public string NameOne { get; set; } 9 10 public string NameTwo { get; set; } 11 }
Note:首先通过流操作把对象(可以是XML,内存中的对象,文本等形式)读取出来,然后通过.NET Framework中的序列化算法把对象进行序列化!
下面就是这三种序列化的不同形式:
DataContractSerializer和NetDataContractSerializer序列化之后都是XML的格式,而DataContractJsonSerializer序列化之后就是常见的Json数据格式!
代码如下:
Note:除了XmlSerializer序列化调用的方法是“Deserialize”,其它的序列化都是使用“ReadObject”进行反序列化操作!
8.一般的Json数据格式
9.理解序列化操作
下午在写公共类库的时候发现序列化其实就是流操作和序列化算法的结合,不管你使用哪一种流操作,最重要的还是你使用的是哪一种序列化算法,有“BinaryFormatter”,“SoapFormatter”,“XmlSerializer”,“DataContractSerialize”,“DataContractJsonSerializer”,“NetDataContractSerializer” 等,它们在序列化之后的格式有一定的差异!
10.关于Json序列化时间的问题
没接触过不知道问题所在,接触过了才能猛然醒悟!
①如果把时间设置为“String”类型,如下:
②如果直接设置为“DataTime”,如下:
11.简单的封装Json操作类,解决时间问题
1 public static class JsonOperation<T>
2 {
3 private static readonly DataContractJsonSerializer DataContractJsonSerializer = new DataContractJsonSerializer(typeof(T));
4
5 //序列化
6 public static string JsonSerializeOperation(T obj)
7 {
8 if (obj == null)
9 throw new Exception();
10 string str = "";
11 using (MemoryStream memoryStream = new MemoryStream())
12 {
13 DataContractJsonSerializer.WriteObject(memoryStream, obj);
14 str = Encoding.UTF8.GetString(memoryStream.ToArray());
15 }
16 return ConvertJsonTimeToDateTime(str);
17 }
18
19 //反序列化
20 public static T JsonDeserializeOperation(string str)
21 {
22 if (string.IsNullOrEmpty(str))
23 throw new Exception();
24 using (MemoryStream memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(str)))
25 {
26 return (T)DataContractJsonSerializer.ReadObject(memoryStream);
27 }
28 }
29
30 //二进制序列化
31 public static string BinarySerializeOperation(T obj)
32 {
33 string jsonString = "";
34 if (obj == null)
35 throw new Exception();
36 IFormatter formatter = new BinaryFormatter();
37 using (MemoryStream memoryStream = new MemoryStream())
38 {
39 formatter.Serialize(memoryStream, obj);
40 jsonString = Encoding.UTF8.GetString(memoryStream.ToArray());
41 }
42 return jsonString;
43 }
44
45 //二进制反序列化
46 public static T BinaryDeserializeOperation(string str)
47 {
48 if (string.IsNullOrEmpty(str))
49 throw new Exception();
50 IFormatter formatter = new BinaryFormatter();
51 using (MemoryStream memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(str)))
52 {
53 return (T)formatter.Deserialize(memoryStream);
54 }
55 }
56
57 /// <summary>
58 /// 把Json中的时间转化为正规时间,现在是Json数据格式,需要转化普通的时间格式 → yyyy-MM-dd HH:MM:ss
59 /// </summary>
60 /// <param name="jsonString">Json Time</param>
61 /// <returns></returns>
62 private static string ConvertJsonTimeToDateTime(string jsonString)
63 {
64 if (string.IsNullOrEmpty(jsonString))
65 throw new Exception();
66 const string matchDate = @"\\/Date\((\d+)\+\d+\)\\/";
67 Regex regex = new Regex(matchDate);
68 Match match = regex.Match(jsonString);
69 foreach (var matchValue in match.Groups)
70 {
71 if (matchValue is Match)
72 {
73 Match matchOne = (Match)matchValue;
74 DateTime dateTime = JsonOperation<DateTime>.JsonDeserializeOperation(string.Format("\"{0}\"", matchOne.Value)); // This is very important.
75 jsonString = jsonString.Replace(matchOne.Value, dateTime.ToString("yyyy-MM-dd HH-MM-ss"));
76 }
77 }
78 return jsonString;
79 }
80 }