我们在程序中经常需要对一个Object做序列化操作,有时希望对特别的属性,标记特别的名称。有几种方法可以实现:
1. 使用JSON.NET类库
这是一个开源的类库,您可以从这里下载。它支持格式化,自定义等功能。我们通常在需要序列化属性下标记即可:
[JsonProperty(Name = "text")]
public string Text { get; set; }
这个属性最后序列化的名字是text.
2. 在.net 4.0 也提供一个DataMember特性类似它,你可能在WCF中有看到过:
[DataMember(Name = "text")]
public string Text { get; set; }
后面发现JSON.NET它也支持这个特性。
下面我们来看一个TreeItem的Object,为了演出这里同时支持两种方法,当然你可选择其中一种。
1: [DataContract]
2: public class TreeItem<TValue> : ITreeNode<TreeItem<TValue>, TValue>
3: {
4: private readonly List<TreeItem<TValue>> children = new List<TreeItem<TValue>>();
5:
6: /// <summary>
7: /// Gets or sets the id.
8: /// </summary>
9: /// <value>The id.</value>
10: /// <remarks>type must be string,because Jquery tree will use it replace method on it</remarks>
11: [DataMember(Name = "id")]
12: public string Id { get; set; }
13:
14:
15: /// <summary>
16: /// Gets or sets a value indicating whether this <see cref="TreeItem"/> is showcheck.
17: /// </summary>
18: /// <value><c>true</c> if showcheck; otherwise, <c>false</c>.</value>
19: [DataMember(Name = "showcheck")]
20: public bool Showcheck { set; get; }
21:
22:
23: /// <summary>
24: /// Gets or sets a value indicating whether this <see cref="TreeItem"/> is isexpand.
25: /// </summary>
26: /// <value><c>true</c> if isexpand; otherwise, <c>false</c>.</value>
27: [DataMember(Name = "isexpand")]
28: public bool Isexpand { set; get; }
29:
30:
31: /// <summary>
32: /// Gets or sets the checkstate.
33: /// </summary>
34: /// <value>The checkstate.</value>
35: [DataMember(Name = "checkstate")]
36: public int Checkstate { get; set; }
37:
38: /// <summary>
39: /// whether load complete(indicating whether async load data)
40: /// Suppose sync load data to node should be true
41: /// </summary>
42: /// <value><c>true</c> if complete; otherwise, <c>false</c>.</value>
43:
44: [DataMember(Name = "complete")]
45: public bool Complete { get; set; }
46:
47: private bool _haschild;
48: /// <summary>
49: /// Gets a value indicating whether this instance has children.
50: /// </summary>
51: /// <value>
52: /// <c>true</c> if this instance has children; otherwise, <c>false</c>.
53: /// </value>
54: [DataMember(Name = "hasChildren")]
55: public bool HasChildren
56: {
57: get { return (Children != null && Children.Count() > 0); }
58: set { _haschild=value;}
59: }
60:
61: #region ITreeNode<TreeItem<TValue>,TValue> Members
62:
63: /// <summary>
64: /// Gets or sets the text.
65: /// </summary>
66: /// <value>The text.</value>
67: [DataMember(Name = "text")]
68: public string Text { get; set; }
69:
70:
71: /// <summary>
72: /// Gets or sets the value.
73: /// </summary>
74: /// <value>The value.</value>
75: [DataMember(Name = "value")]
76: public TValue Value { get; set; }
77:
78: /// <summary>
79: /// Gets or sets the parent.
80: /// </summary>
81: /// <value>The parent.</value>
82: public TreeItem<TValue> Parent { get; set; }
83:
84:
85: /// <summary>
86: /// Gets the children.
87: /// </summary>
88: /// <value>The children.</value>
89: [JsonProperty("ChildNodes")]
90: [DataMember(Name = "ChildNodes")]
91: public IEnumerable<TreeItem<TValue>> Children
92: {
93: get { return children; }
94: }
95:
96: #endregion
97: }
然后用扩展方法,封装一下JSON.NET的方法:
1: public static string ToJsonString<TValue>(this TreeItem<TValue> treeItem)
2: {
3: string sJson = JsonConvert.SerializeObject(
4: treeItem);
5: return "var treedata=[" + sJson + "];";
6: }
7:
8: public static string ToFormatJsonString<TValue>(this TreeItem<TValue> treeItem)
9: {
10: string sJson = JsonConvert.SerializeObject(
11: treeItem
12: , Formatting.Indented,
13: new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() }
14: );
15: return "var treedata=[" + sJson + "];";
16: }
下面是TestMethod:
1: public void TestDataContractJsonSerializer()
2: {
3: var treeitem = new TreeItem<string>();
4: treeitem.Id = "1";
5: treeitem.Text = "Root";
6: treeitem.Value = "3223";
7: treeitem.Isexpand = true;
8: treeitem.Showcheck = true;
9: treeitem.Add(new TreeItem<string>() { Id ="2", Text = "Node2", Value = "9982",Showcheck=true,Isexpand=true,Checkstate=1 });
10:
11: using (MemoryStream stream1 = new MemoryStream())
12: {
13:
14: var ser = new DataContractJsonSerializer(typeof(TreeItem<string>));
15: ser.WriteObject(stream1, treeitem);
16: stream1.Position = 0;
17: StreamReader sr = new StreamReader(stream1);
18:
19: string mstr = "var treedata=[" + sr.ReadToEnd() + "];";
20:
21: Console.WriteLine(mstr);
22:
23: string tstr = treeitem.ToJsonString<string>();
24: Console.WriteLine(tstr);
25:
26: Assert.AreEqual(tstr.Length, mstr.Length);
27: }
28: }
最后这个UnitTest通过了,输出结果如下:
1: var treedata=[{"ChildNodes":[{"ChildNodes":[],"checkstate":1,"complete":true,"hasChildren":false,"id":"2","isexpand":true,"showcheck":true,"text":"Node2","value":"9982"}],"checkstate":0,"complete":true,"hasChildren":true,"id":"1","isexpand":true,"showcheck":true,"text":"Root","value":"3223"}];
2: var treedata=[{"id":"1","showcheck":true,"isexpand":true,"checkstate":0,"complete":true,"hasChildren":true,"text":"Root","value":"3223","ChildNodes":[{"id":"2","showcheck":true,"isexpand":true,"checkstate":1,"complete":true,"hasChildren":false,"text":"Node2","value":"9982","ChildNodes":[]}]}];
3:
4: 1 passed, 0 failed, 0 skipped, took 0.86 seconds (MSTest 10.0).
你会发现它们之间区别是,顺序不同。如果您不希望引用第三方的类库,可以使用.net 4.0 提供的DataContractJsonSerializer 类。
希望对您的开发有帮助。
作者:Petter Liu
出处:http://www.cnblogs.com/wintersun/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
该文章也同时发布在我的独立博客中-Petter Liu Blog。