JavaScriptSerializer中日期序列化問題解決方案
直接進入主題:
class Student { public int age { get; set; } public DateTime? date { get; set; } public string name { get; set; } }
當點擊的時候:
private void button1_Click(object sender, EventArgs e) { System.Web.Script.Serialization.JavaScriptSerializer js = new System.Web.Script.Serialization.JavaScriptSerializer(); List<Student> list = new List<Student>(); list.Add(new Student() { age = 10, date = DateTime.Now, name = "宋興柱 是個好孩\"子,這里\"有英文逗號" }); //js.RegisterConverters(new JavaScriptConverter[] { new DateTimeConverter() }); var str = js.Serialize(list); //str = Regex.Replace(str, @"\\/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"); //}); //var obj = js.Deserialize<List<Student>>(str); textBox1.Text = str; }
這個時候,顯示如下內容:[{"age":10,"date":"\/Date(1404098342309)\/","name":"宋興柱 是個好孩\"子,這里\"有英文逗號"}]
顯然,這里的DateTime 類型被替換成了:\/Date(1404098342309)\/,經過分析,其實這個1404098342309數值,是1970年1月1日(DateTime的最小值)到date實際表示的日期之差的總毫秒數。
因此,這里提供2種解決方案。
方案1 :
private void button1_Click(object sender, EventArgs e) { System.Web.Script.Serialization.JavaScriptSerializer js = new System.Web.Script.Serialization.JavaScriptSerializer(); List<Student> list = new List<Student>(); list.Add(new Student() { age = 10, date = DateTime.Now, name = "宋興柱 是個好孩\"子,這里\"有英文逗號" }); //js.RegisterConverters(new JavaScriptConverter[] { new DateTimeConverter() }); var str = js.Serialize(list); str = Regex.Replace(str, @"\\/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"); }); //var obj = js.Deserialize<List<Student>>(str); textBox1.Text = str; }
顯示結果:[{"age":10,"date":"2014-06-30 11:22:15","name":"宋興柱 是個好孩\"子,這里\"有英文逗號"}]
當取消var obj = js.Deserialize<List<Student>>(str);的注釋之后,會發現反序列化也完全正常。因此,這算是當前的最佳方案。
方案2 :
如果用戶的日期需求中,只用到年月日,無需時分秒的情況下:如,2014-06-30 時,可以使用如下方案:
public class DateTimeConverter : JavaScriptConverter { public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer) { return new JavaScriptSerializer().ConvertToType(dictionary, type); } public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer) { if (!(obj is DateTime)) return null; return new CustomString(((DateTime)obj).ToString("yyyy-MM-dd")); } public override IEnumerable<Type> SupportedTypes { get { return new[] { typeof(DateTime) }; } } private class CustomString : Uri, IDictionary<string, object> { public CustomString(string str) : base(str, UriKind.Relative) { } void IDictionary<string, object>.Add(string key, object value) { throw new NotImplementedException(); } bool IDictionary<string, object>.ContainsKey(string key) { throw new NotImplementedException(); } ICollection<string> IDictionary<string, object>.Keys { get { throw new NotImplementedException(); } } bool IDictionary<string, object>.Remove(string key) { throw new NotImplementedException(); } bool IDictionary<string, object>.TryGetValue(string key, out object value) { throw new NotImplementedException(); } ICollection<object> IDictionary<string, object>.Values { get { throw new NotImplementedException(); } } object IDictionary<string, object>.this[string key] { get { throw new NotImplementedException(); } set { throw new NotImplementedException(); } } void ICollection<KeyValuePair<string, object>>.Add(KeyValuePair<string, object> item) { throw new NotImplementedException(); } void ICollection<KeyValuePair<string, object>>.Clear() { throw new NotImplementedException(); } bool ICollection<KeyValuePair<string, object>>.Contains(KeyValuePair<string, object> item) { throw new NotImplementedException(); } void ICollection<KeyValuePair<string, object>>.CopyTo(KeyValuePair<string, object>[] array, int arrayIndex) { throw new NotImplementedException(); } int ICollection<KeyValuePair<string, object>>.Count { get { throw new NotImplementedException(); } } bool ICollection<KeyValuePair<string, object>>.IsReadOnly { get { throw new NotImplementedException(); } } bool ICollection<KeyValuePair<string, object>>.Remove(KeyValuePair<string, object> item) { throw new NotImplementedException(); } IEnumerator<KeyValuePair<string, object>> IEnumerable<KeyValuePair<string, object>>.GetEnumerator() { throw new NotImplementedException(); } IEnumerator IEnumerable.GetEnumerator() { throw new NotImplementedException(); } }
點擊按鈕時,注冊即可:
private void button1_Click(object sender, EventArgs e) { System.Web.Script.Serialization.JavaScriptSerializer js = new System.Web.Script.Serialization.JavaScriptSerializer(); List<Student> list = new List<Student>(); list.Add(new Student() { age = 10, date = DateTime.Now, name = "宋興柱 是個好孩\"子,這里\"有英文逗號" }); js.RegisterConverters(new JavaScriptConverter[] { new DateTimeConverter() }); var str = js.Serialize(list); //str = Regex.Replace(str, @"\\/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"); //}); //var obj = js.Deserialize<List<Student>>(str); textBox1.Text = str; }
執行效果如下:[{"age":10,"date":"2014-06-30","name":"宋興柱 是個好孩\"子,這里\"有英文逗號"}]
對於方案二來說,由於內部使用的是Uri類,因此,將日期轉為字符串如:2014-06-30 11:30:00這 種樣式的時候,中間的空格,會被進行Url編碼:空格會被編碼成:%20。因此會損壞原有的日期格式。不過方案二對於其它類型的使用,依然有借鑒之處。還忘不斷探索。
------------------- 繁星小宋:宋興柱(Sindrol)於2014-06-30:11:31分