1.DataContractJsonSerializer

DataContractJsonSerializer在System.Runtime.Serialization.Json命名空间下,.NETFramework 3.5包含在System.ServiceModel.Web.dll中,需要添加对其的引用;.NETFramework 4在System.Runtime.Serialization中

序列化对象示例:



public class Person
    {
        public int Age { get; set; }
        public string Name { get; set; }
        /// <summary>
        /// 涉及时间转换问题
        /// </summary>
        public DateTime BirthDay { get; set; }
        /// <summary>
        /// Dictionary
        /// </summary>
        public Dictionary<string, int> Subjects { get; set; }
        public Address Adress { get; set; }
        /// <summary>
        /// 集合类型
        /// </summary>
        public List<Role> RoleList { get; set; }
        /// <summary>
        /// 枚举接口
        /// </summary>
        public IEnumerable<Department> Departments { get; set; }
        /// <summary>
        /// 数组问题
        /// </summary>
        public string[] favoriteFruit { get; set; }

    }
    public class Role
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }
    public class Address
    {
        public string Province { get; set; }
        public string City { get; set; }
        public string District { get; set; }
    }
    public class Department
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }

简单封装下DataContractSerializer,如下:



1. public static class
2. {  
3. public static T DeserializeFromString<T>(string str) where T : class
4.         {  
5. try
6.             {  
7.   
8. byte[] buffer = Encoding.UTF8.GetBytes(str);  
9. new
10. new DataContractJsonSerializer(typeof(T));  
11. return ser.ReadObject(ms) as
12.             }  
13. catch
14.             {  
15. return null;  
16.             }  
17.         }  
18. public static string SerializeToString<T>(T t) where T : class
19.         {  
20. try
21.             {  
22. new DataContractJsonSerializer(typeof(T));  
23. string result = string.Empty;  
24. using (MemoryStream ms = new
25.                 {  
26.                     ser.WriteObject(ms, t);  
27.                     result = Encoding.UTF8.GetString(ms.ToArray());  
28.                 }  
29.   
30. return
31.             }  
32. catch
33.             {  
34. return null;  
35.             }  
36.         }  
37. }


public static class JsonHelper
{
        public static T DeserializeFromString<T>(string str) where T : class
        {
            try
            {

                byte[] buffer = Encoding.UTF8.GetBytes(str);
                MemoryStream ms = new MemoryStream(buffer, 0, buffer.Length);
                DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(T));
                return ser.ReadObject(ms) as T;
            }
            catch (Exception e)
            {
                return null;
            }
        }
        public static string SerializeToString<T>(T t) where T : class
        {
            try
            {
                DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(T));
                string result = string.Empty;
                using (MemoryStream ms = new MemoryStream())
                {
                    ser.WriteObject(ms, t);
                    result = Encoding.UTF8.GetString(ms.ToArray());
                }

                return result;
            }
            catch
            {
                return null;
            }
        }
}



序列化代码如下:



1. Person p = new
2. p.Adress = new
3. {  
4. "江西",  
5. "九江",  
6. "D1"
7. };  
8. p.Age = 20;  
9. p.Name = "张三";  
10. p.BirthDay = DateTime.Parse("1990-09-09 09:00:00");  
11. p.Subjects = new Dictionary<string, int> { { "java", 99 }, { ".net", 100 } };  
12. p.RoleList = new List<Role>() { new Role() { Id = 1, Name = "Role1" }, new Role { Id = 2, Name = "Role2"
13. p.favoriteFruit = new string[] { "apple", "banana"
14. p.Departments = new List<Department>() { new Department() { Id = 1, Name = "DP1" }, new Department() { Id = 2, Name = "DP2"
15. string


Person p = new Person();
            p.Adress = new Address
            {
                Province = "江西",
                City = "九江",
                District = "D1"
            };
            p.Age = 20;
            p.Name = "张三";
            p.BirthDay = DateTime.Parse("1990-09-09 09:00:00");
            p.Subjects = new Dictionary<string, int> { { "java", 99 }, { ".net", 100 } };
            p.RoleList = new List<Role>() { new Role() { Id = 1, Name = "Role1" }, new Role { Id = 2, Name = "Role2" } };
            p.favoriteFruit = new string[] { "apple", "banana" };
            p.Departments = new List<Department>() { new Department() { Id = 1, Name = "DP1" }, new Department() { Id = 2, Name = "DP2" } };
            string s = JsonHelper.SerializeToString<Person>(p);


结果如下:

java 对象json 序列化 json序列化顺序_Parse

以vs中的json格式化工具查看:



java 对象json 序列化 json序列化顺序_List_02

问题1:日期时间格式问题,注意序列化后的json字符串(文本形式,vs的json查看器会自动处理日期时间格式),JSON格式不直接支持日期和时间。DateTime值值显示为“Date(652842000000+0800)”形式的JSON字符串,其中第一个数字(在提供的示例中为 Date(652842000000+0800))是 GMT 时区中自 1970 年 1 月 1 日午夜以来按正常时间(非夏令时)经过的毫秒数。该数字可以是负数,以表示之前的时间。示例中包括“+0800”的部分可选,它指示该时间属于Local类型,即它在反序列化时应转换为本地时区。如果没有该部分,则会将时间反序列化为Utc。

解决办法:在序列化和反序列化时,对json字符串中的日期进行处理。修改序列化处理类如下:

1. public static class
2.     {  
3.   
4. public static T DeserializeFromString<T>(string str) where T : class
5.         {  
6. try
7.             {  
8. //增加时间处理
9. string p = @"\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2}";  
10. new
11.                 str = reg.Replace(str, r =>  
12.                 {  
13. string result = string.Empty;  
14.                     DateTime dt = DateTime.Parse(r.Groups[0].Value);  
15.                     dt = dt.ToUniversalTime();  
16. "1970-01-01");  
17. string.Format("\\/Date({0}+0800)\\/", ts.TotalMilliseconds);  
18. return
19.                 });  
20. byte[] buffer = Encoding.UTF8.GetBytes(str);  
21. new
22. new DataContractJsonSerializer(typeof(T));  
23. return ser.ReadObject(ms) as
24.             }  
25. catch
26.             {  
27. return null;  
28.             }  
29.         }  
30. public static string SerializeToString<T>(T t) where T : class
31.         {  
32. try
33.             {  
34. new DataContractJsonSerializer(typeof(T));  
35. string result = string.Empty;  
36. using (MemoryStream ms = new
37.                 {  
38.                     ser.WriteObject(ms, t);  
39.                     result = Encoding.UTF8.GetString(ms.ToArray());  
40.                 }  
41. // 增加处理时间
42. string p = @"\\/Date(\d+)\+\d+\\/";  
43. new
44.                 result = reg.Replace(result, r =>  
45.                 {  
46. string ret = string.Empty;  
47. new
48. long.Parse(r.Groups[1].Value));  
49.                     dt = dt.ToLocalTime();  
50. "yyyy-MM-dd HH:mm:ss");  
51. return
52.                 });  
53. return
54.             }  
55. catch
56.             {  
57. return null;  
58.             }  
59.         }  
60.     }


public static class JsonHelper
    {

        public static T DeserializeFromString<T>(string str) where T : class
        {
            try
            {
                //增加时间处理
                string p = @"\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2}";
                Regex reg = new Regex(p);
                str = reg.Replace(str, r =>
                {
                    string result = string.Empty;
                    DateTime dt = DateTime.Parse(r.Groups[0].Value);
                    dt = dt.ToUniversalTime();
                    TimeSpan ts = dt - DateTime.Parse("1970-01-01");
                    result = string.Format("\\/Date({0}+0800)\\/", ts.TotalMilliseconds);
                    return result;
                });
                byte[] buffer = Encoding.UTF8.GetBytes(str);
                MemoryStream ms = new MemoryStream(buffer, 0, buffer.Length);
                DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(T));
                return ser.ReadObject(ms) as T;
            }
            catch (Exception e)
            {
                return null;
            }
        }
        public static string SerializeToString<T>(T t) where T : class
        {
            try
            {
                DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(T));
                string result = string.Empty;
                using (MemoryStream ms = new MemoryStream())
                {
                    ser.WriteObject(ms, t);
                    result = Encoding.UTF8.GetString(ms.ToArray());
                }
                // 增加处理时间
                string p = @"\\/Date\((\d+)\+\d+\)\\/";
                Regex reg = new Regex(p);
                result = reg.Replace(result, r =>
                {
                    string ret = string.Empty;
                    DateTime dt = new DateTime(1970, 1, 1);
                    dt = dt.AddMilliseconds(long.Parse(r.Groups[1].Value));
                    dt = dt.ToLocalTime();
                    ret = dt.ToString("yyyy-MM-dd HH:mm:ss");
                    return ret;
                });
                return result;
            }
            catch
            {
                return null;
            }
        }
    }

修改完重新序列化后如下:

java 对象json 序列化 json序列化顺序_序列化_03

测试下反序列化:



1. string s = "{\"Adress\":{\"City\":\"九江\",\"District\":\"D1\",\"Province\":\"江西\"},\"Age\":20,\"BirthDay\":\"1990-09-09 09:00:00\",\"Departments\":[{\"Id\":1,\"Name\":\"DP1\"},{\"Id\":2,\"Name\":\"DP2\"}],\"Name\":\"张三\",\"RoleList\":[{\"Id\":1,\"Name\":\"Role1\"},{\"Id\":2,\"Name\":\"Role2\"}],\"Subjects\":[{\"Key\":\"java\",\"Value\":99},{\"Key\":\".net\",\"Value\":100}],\"favoriteFruit\":[\"apple\",\"banana\"]}";  
2.   
3. Person p = JsonHelper.DeserializeFromString<Person>(s);


string s = "{\"Adress\":{\"City\":\"九江\",\"District\":\"D1\",\"Province\":\"江西\"},\"Age\":20,\"BirthDay\":\"1990-09-09 09:00:00\",\"Departments\":[{\"Id\":1,\"Name\":\"DP1\"},{\"Id\":2,\"Name\":\"DP2\"}],\"Name\":\"张三\",\"RoleList\":[{\"Id\":1,\"Name\":\"Role1\"},{\"Id\":2,\"Name\":\"Role2\"}],\"Subjects\":[{\"Key\":\"java\",\"Value\":99},{\"Key\":\".net\",\"Value\":100}],\"favoriteFruit\":[\"apple\",\"banana\"]}";

Person p = JsonHelper.DeserializeFromString<Person>(s);

结果如下:

java 对象json 序列化 json序列化顺序_Parse_04

问题2:序列化后的json数据,字符串显示的顺序不对,例如,Age应该处理第一个json属性,现在发现是第二个,另外我们对Age序列化后显示的名称有要求,要显示为PersonAge。这种需求,可以通过Person类运用DataContract和Age属性运用DataMember特性来进行设置,例如我们现在只对Person有要求,修改如下:



1. [DataContract]  
2. public class
3.     {  
4. "PersonAge")]  
5. public int Age { get; set; }  
6. public string Name { get; set; }  
7. public DateTime BirthDay { get; set; }  
8. public Dictionary<string, int> Subjects { get; set; }  
9. public Address Adress { get; set; }  
10. public List<Role> RoleList { get; set; }  
11. public IEnumerable<Department> Departments { get; set; }  
12. public string[] favoriteFruit { get; set; }  
13. }


[DataContract]
    public class Person
    {
        [DataMember(Order = 1, Name = "PersonAge")]
        public int Age { get; set; }
        public string Name { get; set; }
        public DateTime BirthDay { get; set; }
        public Dictionary<string, int> Subjects { get; set; }
        public Address Adress { get; set; }
        public List<Role> RoleList { get; set; }
        public IEnumerable<Department> Departments { get; set; }
        public string[] favoriteFruit { get; set; }
}



序列化后结果如下:


java 对象json 序列化 json序列化顺序_List_05

什么情况?怎么只序列化了一个Peron类中的Age属性?原来当我们使用数据契约(DataContract)来描述的类的序列化时,只有我们显式的把这个类当中的具体的成员通过DataMember来标记了,才表明这个成员是要参与到序列化当中,如果某一个成员没有使用DataMember来标记,表明这个成员不需要参与到序列化当中。因此我们再修改一下:



1. [DataContract]  
2. public class
3.     {  
4. "PersonAge")]  
5. public int Age { get; set; }  
6.         [DataMember(Order = 2)]  
7. public string Name { get; set; }  
8.         [DataMember(Order = 3)]  
9. public DateTime BirthDay { get; set; }  
10.         [DataMember(Order = 4)]  
11. public Dictionary<string, int> Subjects { get; set; }  
12.         [DataMember(Order = 5)]  
13. public Address Adress { get; set; }  
14.         [DataMember(Order = 6)]  
15. public List<Role> RoleList { get; set; }  
16.         [DataMember(Order = 7)]  
17. public IEnumerable<Department> Departments { get; set; }  
18.         [DataMember(Order = 8)]  
19. public string[] favoriteFruit { get; set; }  
20.     }


[DataContract]
    public class Person
    {
        [DataMember(Order = 1, Name = "PersonAge")]
        public int Age { get; set; }
        [DataMember(Order = 2)]
        public string Name { get; set; }
        [DataMember(Order = 3)]
        public DateTime BirthDay { get; set; }
        [DataMember(Order = 4)]
        public Dictionary<string, int> Subjects { get; set; }
        [DataMember(Order = 5)]
        public Address Adress { get; set; }
        [DataMember(Order = 6)]
        public List<Role> RoleList { get; set; }
        [DataMember(Order = 7)]
        public IEnumerable<Department> Departments { get; set; }
        [DataMember(Order = 8)]
        public string[] favoriteFruit { get; set; }
    }



结果如下:


java 对象json 序列化 json序列化顺序_List_06


问题3:Serializable特性问题,如果我们在Person类中只运用Serializable特性(不运用DataContract)时会发生什么情况,如下:



[Serializable]
public class Person
{
}

序列的结果如下:


java 对象json 序列化 json序列化顺序_Parse_07



要修复这个问题,两个办法,1、去掉Serializable特性,2、在运用Serializable特性的类中额外加上DataContract以及属性中添加DataMember特性。

注意,如果只运用Serializable特性,如果将正常的json字符串反序列,也不能正常反序列化,反序列化的json字段也必须是类似_backingField这种的。




2.JavaScriptSerializer


JSON序列化和反序列化还可以使用JavaScriptSerializer,在System.Web.Script.Serializatioin命名空间下,需引用System.Web.Extensions.dll,简单的封装了下JavaScriptSerializer,如下:






public static class JsonHelper
    {
        public static string Serializer(object obj)
        {
            try
            {
                JavaScriptSerializer ser = new JavaScriptSerializer();
                string result = ser.Serialize(obj);
                // 增加处理时间
                string p = @"\\/Date\((\d+)\)\\/";
                Regex reg = new Regex(p);
                result = reg.Replace(result, r =>
                {
                    string ret = string.Empty;
                    DateTime dt = new DateTime(1970, 1, 1);
                    dt = dt.AddMilliseconds(long.Parse(r.Groups[1].Value));
                    dt = dt.ToLocalTime();
                    ret = dt.ToString("yyyy-MM-dd HH:mm:ss");
                    return ret;
                });
                return result;
            }
            catch
            {
                return null;
            }
        }
        public static T Deserializer<T>(string str)
        {
            try
            {
                JavaScriptSerializer ser = new JavaScriptSerializer();
                return ser.Deserialize<T>(str);
            }
            catch
            {
                return default(T);
            }
        }
    }



序列化对象还使用第1章节中的Person对象,序列化如下:






Person p = new Person();
            p.Adress = new Address
            {
                Province = "江西",
                City = "九江",
                District = "D1"
            };
            p.Age = 20;
            p.Name = "张三";
            p.BirthDay = DateTime.Parse("1990-09-09 09:00:00");
            p.Subjects = new Dictionary<string, int> { { "java", 99 }, { ".net", 100 } };
            p.RoleList = new List<Role>() { new Role() { Id = 1, Name = "Role1" }, new Role { Id = 2, Name = "Role2" } };
            p.favoriteFruit = new string[] { "apple", "banana" };
            p.Departments = new List<Department>() { new Department() { Id = 1, Name = "DP1" }, new Department() { Id = 2, Name = "DP2" } };
            string s = JsonHelper.Serializer(p);

结果:



java 对象json 序列化 json序列化顺序_java 对象json 序列化_08

java 对象json 序列化 json序列化顺序_List_09

 

问题1:日期时间格式问题与DataContractJsonSerializer一样,同样存在格式问题,处理方式与DataContractJsonSerializer一致。

问题2:JavascriptSerializer和DataContractJsonSerializer有一点不一样,即无DataContract和DataMemeber特性,因此对于JavaScriptSerializer序列化的对象,序列化后的字段名称与对象属性名称是一致的,且无处设置。



java 对象json 序列化 json序列化顺序_序列化_10


问题3:Serializable特性问题,JavaScriptSerializer对于序列化的对象,不考虑序列化对象的Serializable特性问题。因此对于自动属性也不会序列成xx_backingField。

问题4:JavaScriptSerializer可以序列化匿名对象。




1. var o = new { Id = 1, Name = "jack", Address = "China"
2. string


var o = new { Id = 1, Name = "jack", Address = "China" };
    string s = JsonHelper.Serializer(o);



结果:


java 对象json 序列化 json序列化顺序_序列化_11



问题5:怎么将字符串反序列化匿名对象呢? 可以使用第三方Newtonsoft.Json。

3.Newtonsoft.Json


Newtonsoft.Json是一款.NET中开源的Json序列化和反序列化类库,可通过http://www.newtonsoft.com/json下载。

该类库中最常用的两个方法:JsonConvert.SerializeObject和JsonConvert.DeserializeObject。

简单的封装下:




1. public static class
2.    {  
3. public static string Serializer(object
4.        {  
5. return
6.        }  
7. public static T Deserializer<T>(string
8.        {  
9. return
10.        }  
11.    }



public static class JsonHelper
    {
        public static string Serializer(object obj)
        {
            return JsonConvert.SerializeObject(obj);
        }
        public static T Deserializer<T>(string str)
        {
            return JsonConvert.DeserializeObject<T>(str);
        }
    }

序列化对象依然引用第1章节中的Person对象,序列化如下:




1. Person p = new
2. new
3.             {  
4. "江西",  
5. "九江",  
6. "D1"
7.             };  
8.             p.Age = 20;  
9. "张三";  
10. "1990-09-09 09:00:00");  
11. new Dictionary<string, int> { { "java", 99 }, { ".net", 100 } };  
12. new List<Role>() { new Role() { Id = 1, Name = "Role1" }, new Role { Id = 2, Name = "Role2"
13. new string[] { "apple", "banana"
14. new List<Department>() { new Department() { Id = 1, Name = "DP1" }, new Department() { Id = 2, Name = "DP2"
15.   
16. string



Person p = new Person();
            p.Adress = new Address
            {
                Province = "江西",
                City = "九江",
                District = "D1"
            };
            p.Age = 20;
            p.Name = "张三";
            p.BirthDay = DateTime.Parse("1990-09-09 09:00:00");
            p.Subjects = new Dictionary<string, int> { { "java", 99 }, { ".net", 100 } };
            p.RoleList = new List<Role>() { new Role() { Id = 1, Name = "Role1" }, new Role { Id = 2, Name = "Role2" } };
            p.favoriteFruit = new string[] { "apple", "banana" };
            p.Departments = new List<Department>() { new Department() { Id = 1, Name = "DP1" }, new Department() { Id = 2, Name = "DP2" } };

            string s = JsonHelper.Serializer(p);

结果如下:



java 对象json 序列化 json序列化顺序_java 对象json 序列化_12

java 对象json 序列化 json序列化顺序_Parse_13


问题1:日期时间格式问题在Newtonsoft.Json能正常解释,不存在此问题。

问题2:Serializer特性不受影响,与JavascriptSerializer类似。

问题3:将对象反序列化成匿名对象,在JsonHelper类中添加如下方法:



1. public static T DeserializerAnonymousType<T>(string
2.        {  
3. return
4.        }

public static T DeserializerAnonymousType<T>(string str, T t)
        {
            return JsonConvert.DeserializeAnonymousType<T>(str, t);
        }



反序列化成匿名对象示例如下:






var obj = new { Id = 0, Name = "", Address = "" };
string jsonStr = @"{'Id':'1','Name':'zhangsan','Address':'china'}";
obj = JsonHelper.DeserializerAnonymousType(jsonStr, obj);



结果:



java 对象json 序列化 json序列化顺序_List_14