.Net 2.0: Entity as DTO vs Dataset as DTO / Xml Serialization vs JSON Serialization
2006-04-18 16:40
603 查看
本文以一组Entity vs Dataset的性能测试数据为基础,比较以Entity作为DTO和Dataset作为DTO的性能差异。测试可能不一定严密,但是一定程度上能够比较出优劣。希望能为您选择 .Net下不同的数据承载方式、序列化方式、DTO的选择,多一点参考。在本测试中,每个执行过程,对于Entity,我们将先用DataReader读出数据,使用索引将数据填充到Entity,序列化,再反序列化;对于Dataset,将先读取所有数据到Dataset,序列化,再反序列化,最后通过索引填充Dataset中的数据到Entity。也就是说,无论对Entity还是Dataset,我们都尽可能的取其最佳性能的执行方式,从而将性能瓶颈留在了序列化和反序列化方式上。您可以注意到,Dataset的序列化和反序列化性能是非常突出的,但是,我们基于Entity的自定义序列化方式的综合性能,超越了Dataset。
04/18补充:新增.NET JSON序列化对照。关于JSON的更多介绍请参见:http://www.json.org/。不过值得一提的是,官方提供的.Net实现写得那个烂得简直没话说。本测试使用Teddy修改由化后的.Net版本,性能是官方版本的30-40倍。
测试报告
就让我们先从一个测试报告开始,该测试读取Northwind数据库中Order Details Extended视图的所有数据,RepeatTime表示每个步骤(读数据、序列化、反序列化等等着每个步骤)被重复的次数。表中的时间数值单位为毫秒。
Repeat Time = 10
Repeat Time = 20
Repeat Time = 30
Repeat Time = 40
解析
以上的测试中,除了Dataset Serialize是使用Dataset作为DTO来序列化和反序列化数据之外,其他的都是使用Entity方式来处理。Xml Serialize表示系统默认的XmlSerializer序列化方式,SoapSerilialize自然是系统默认的SoapFormatter序列化,CustomSerialize则是自定义的序列化方式(目前采用的是自定义序列化+XmlSerializer反序列化结合的方式)。Json Serialization为Teddy的Json优化版本。
测试代码
1
using System;
2
using System.Data;
3
using System.Collections;
4
using System.Configuration;
5
using System.Web;
6
using System.Web.Security;
7
using System.Web.UI;
8
using System.Web.UI.WebControls;
9
using System.Web.UI.WebControls.WebParts;
10
using System.Web.UI.HtmlControls;
11
using Ilungasoft.Framework.Common;
12
using Ilungasoft.Framework.Data.Facade;
13
14
public partial class _Default : System.Web.UI.Page
15
{
16
protected void Page_Load(object sender, EventArgs e)
17
{
18
repeatTime = 10;
19
reportView1.DataSource = DoTest();
20
21
repeatTime = 20;
22
reportView2.DataSource = DoTest();
23
24
repeatTime = 30;
25
reportView3.DataSource = DoTest();
26
27
repeatTime = 40;
28
reportView4.DataSource = DoTest();
29
30
DataBind();
31
}
32
33
private TestReport[] DoTest()
34
{
35
TestReport[] testReports = new TestReport[5];
36
testReports[0] = DoTest1();
37
testReports[1] = DoTest2();
38
testReports[2] = DoTest3();
39
testReports[3] = DoTest4();
40
testReports[4] = DoTest5();
41
42
return testReports;
43
}
44
45
private long time;
46
private DataSet ds;
47
private Order_nbsp_Details_nbsp_Extended[] orderDetails;
48
public string xml;
49
private int repeatTime = 10;
50
51
private TestReport DoTest1()
52
{
53
TestReport testReport = new TestReport();
54
testReport.Title = "Entities Xml Serialize";
55
56
time = System.Environment.TickCount;
57
for (int i = 0; i < repeatTime; i++)
58
orderDetails = DefaultGateway.SelectAll<Order_nbsp_Details_nbsp_Extended>();
59
testReport.ReadDataTime = System.Environment.TickCount - time;
60
61
time = System.Environment.TickCount;
62
for (int i = 0; i < repeatTime; i++)
63
xml = SerializeHelper.SerializeArray(orderDetails);
64
testReport.SerializeTime = System.Environment.TickCount - time;
65
testReport.SerializedXmlSize = xml.Length;
66
67
time = System.Environment.TickCount;
68
for (int i = 0; i < repeatTime; i++)
69
orderDetails = SerializeHelper.Deserialize<Order_nbsp_Details_nbsp_Extended[]>(EntityFactory<Order_nbsp_Details_nbsp_Extended>.GetDynamicEntityType().MakeArrayType(), xml);
70
testReport.DeserializeTime = System.Environment.TickCount - time;
71
72
testReport.TotalRunTime = testReport.ReadDataTime + testReport.SerializeTime + testReport.DeserializeTime;
73
74
return testReport;
75
}
76
77
private TestReport DoTest2()
78
{
79
TestReport testReport = new TestReport();
80
testReport.Title = "Entities Soap Serialize";
81
82
time = System.Environment.TickCount;
83
for (int i = 0; i < repeatTime; i++)
84
orderDetails = DefaultGateway.SelectAll<Order_nbsp_Details_nbsp_Extended>();
85
testReport.ReadDataTime = System.Environment.TickCount - time;
86
87
time = System.Environment.TickCount;
88
for (int i = 0; i < repeatTime; i++)
89
xml = SerializeHelper.SoapSerialize(orderDetails);
90
testReport.SerializeTime = System.Environment.TickCount - time;
91
testReport.SerializedXmlSize = xml.Length;
92
93
time = System.Environment.TickCount;
94
for (int i = 0; i < repeatTime; i++)
95
orderDetails = SerializeHelper.SoapDeserialize<Order_nbsp_Details_nbsp_Extended[]>(xml);
96
testReport.DeserializeTime = System.Environment.TickCount - time;
97
98
testReport.TotalRunTime = testReport.ReadDataTime + testReport.SerializeTime + testReport.DeserializeTime;
99
100
return testReport;
101
}
102
103
private TestReport DoTest3()
104
{
105
TestReport testReport = new TestReport();
106
testReport.Title = "Entities Custom Serialize";
107
108
time = System.Environment.TickCount;
109
for (int i = 0; i < repeatTime; i++)
110
orderDetails = DefaultGateway.SelectAll<Order_nbsp_Details_nbsp_Extended>();
111
testReport.ReadDataTime = System.Environment.TickCount - time;
112
113
time = System.Environment.TickCount;
114
for (int i = 0; i < repeatTime; i++)
115
xml = SerializeHelper.SerializeEntityArray(orderDetails);
116
testReport.SerializeTime = System.Environment.TickCount - time;
117
testReport.SerializedXmlSize = xml.Length;
118
119
time = System.Environment.TickCount;
120
for (int i = 0; i < repeatTime; i++)
121
orderDetails = SerializeHelper.DeserializeEntityArray<Order_nbsp_Details_nbsp_Extended>(xml);
122
testReport.DeserializeTime = System.Environment.TickCount - time;
123
124
testReport.TotalRunTime = testReport.ReadDataTime + testReport.SerializeTime + testReport.DeserializeTime;
125
126
return testReport;
127
}
128
129
private TestReport DoTest4()
130
{
131
TestReport testReport = new TestReport();
132
testReport.Title = "DataSet Serialize";
133
134
time = System.Environment.TickCount;
135
for (int i = 0; i < repeatTime; i++)
136
ds = DefaultGateway.SelectDataSet("select * from [Order Details Extended]");
137
testReport.ReadDataTime = System.Environment.TickCount - time;
138
139
time = System.Environment.TickCount;
140
for (int i = 0; i < repeatTime; i++)
141
{
142
System.IO.MemoryStream ms = new System.IO.MemoryStream();
143
ds.WriteXml(ms);
144
xml = System.Text.UTF8Encoding.UTF8.GetString(ms.ToArray());
145
}
146
testReport.SerializeTime = System.Environment.TickCount - time;
147
testReport.SerializedXmlSize = xml.Length;
148
149
time = System.Environment.TickCount;
150
for (int i = 0; i < repeatTime; i++)
151
{
152
System.IO.MemoryStream ms = new System.IO.MemoryStream(System.Text.UTF8Encoding.UTF8.GetBytes(xml));
153
ds.ReadXml(ms);
154
orderDetails = DefaultGateway.CreateList<Order_nbsp_Details_nbsp_Extended>(ds.Tables[0]);
155
}
156
testReport.DeserializeTime = System.Environment.TickCount - time;
157
158
testReport.TotalRunTime = testReport.ReadDataTime + testReport.SerializeTime + testReport.DeserializeTime;
159
160
return testReport;
161
}
162
163
private TestReport DoTest5()
164
{
165
TestReport testReport = new TestReport();
166
testReport.Title = "Entities JSON Serialize";
167
168
time = System.Environment.TickCount;
169
for (int i = 0; i < repeatTime; i++)
170
orderDetails = DefaultGateway.SelectAll<Order_nbsp_Details_nbsp_Extended>();
171
testReport.ReadDataTime = System.Environment.TickCount - time;
172
173
time = System.Environment.TickCount;
174
for (int i = 0; i < repeatTime; i++)
175
xml = SerializeHelper.JsonSerializeEntityArray(orderDetails);
176
testReport.SerializeTime = System.Environment.TickCount - time;
177
testReport.SerializedXmlSize = xml.Length;
178
179
time = System.Environment.TickCount;
180
for (int i = 0; i < repeatTime; i++)
181
orderDetails = SerializeHelper.JsonDeserializeEntityArray<Order_nbsp_Details_nbsp_Extended>(xml);
182
testReport.DeserializeTime = System.Environment.TickCount - time;
183
184
testReport.TotalRunTime = testReport.ReadDataTime + testReport.SerializeTime + testReport.DeserializeTime;
185
186
return testReport;
187
}
188
}
更多代码我就不列举了,请自行下载下面的源码。
下载
下载测试框架及源码 (本示例源码包含在新版本的Ilungasoft Framework v1.4.4的目录中的dist/Sample5)
小结
本测试示例的目的并不是要终结Dataset作为DTO,尽管Entity作为DTO的性能是可以超越Dataset的,但Teddy觉得,Dataset的性能确实是相当好的,作为一个通用的DTO还是非常适合的(尤其是可以和异构的其他.Net系统方便共享和传递数据)。
补遗:
后续的测试中还发现,无论是XmlSerializer的序列化方式都不够稳定,特别是反序列化时,尤其是对符合类型和数组的序列化。因此,对于大多数基于.Net的程序构架,Teddy还是推荐使用Dataset作为DTO,除非对性能要求非常高时在使用自定义的序列化方式。
4/19:
更新了CustomSerizlize算法,使得其执行时间仅为Dataset的1/2 - 1/10。数据量越大,自定义序列化的优势就越明显。
新增的JSON序列化性能基本和自定义Xml 序列化相当,当数据量较大时,要比自定义Xml序列化方式稍好一点点。
但是,请注意,JSON的序列化后的文本大小只有Dataset的一半,对于需要远程通信的程序来讲,JSON方式将极大的减少需要通信的数据量,因此,JSON方式带来的实际的性能提升可能会更大。
04/18补充:新增.NET JSON序列化对照。关于JSON的更多介绍请参见:http://www.json.org/。不过值得一提的是,官方提供的.Net实现写得那个烂得简直没话说。本测试使用Teddy修改由化后的.Net版本,性能是官方版本的30-40倍。
测试报告
就让我们先从一个测试报告开始,该测试读取Northwind数据库中Order Details Extended视图的所有数据,RepeatTime表示每个步骤(读数据、序列化、反序列化等等着每个步骤)被重复的次数。表中的时间数值单位为毫秒。
Ilungasoft Framework Data Access & Entities Serialization Performance Test
Title | Read Data Time | Serialize Time | Serialized Xml Size | DeserializeTime | Total Run Time |
---|---|---|---|---|---|
Entities Xml Serialize | 844 | 1766 | 702783 | 1750 | 4360 |
Entities Soap Serialize | 328 | 4094 | 3031007 | 6203 | 10625 |
Entities Custom Serialize | 359 | 594 | 598565 | 625 | 1578 |
DataSet Serialize | 515 | 532 | 586200 | 2047 | 3094 |
Entities JSON Serialize | 484 | 625 | 325298 | 641 | 1750 |
Title | Read Data Time | Serialize Time | Serialized Xml Size | Deserialize Time | Total Run Time |
---|---|---|---|---|---|
Entities Xml Serialize | 1093 | 2594 | 702783 | 3797 | 7484 |
Entities Soap Serialize | 734 | 8032 | 3031007 | 12000 | 20766 |
Entities Custom Serialize | 671 | 1188 | 598565 | 1234 | 3093 |
DataSet Serialize | 657 | 1062 | 586200 | 6563 | 8282 |
Entities JSON Serialize | 781 | 1094 | 325298 | 1093 | 2968 |
Title | Read Data Time | Serialize Time | Serialized Xml Size | Deserialize Time | Total Run Time |
---|---|---|---|---|---|
Entities Xml Serialize | 938 | 4140 | 702783 | 5547 | 10625 |
Entities Soap Serialize | 1094 | 12578 | 3031007 | 18891 | 32563 |
Entities Custom Serialize | 1140 | 1922 | 598565 | 2188 | 5250 |
DataSet Serialize | 1156 | 1438 | 586200 | 14984 | 17578 |
Entities JSON Serialize | 1141 | 1656 | 325298 | 1703 | 4500 |
Title | Read Data Time | Serialize Time | Serialized Xml Size | Deserialize Time | Total Run Time |
---|---|---|---|---|---|
Entities Xml Serialize | 1594 | 5047 | 702783 | 6968 | 13609 |
Entities Soap Serialize | 1391 | 16844 | 3031007 | 26093 | 44328 |
Entities Custom Serialize | 1875 | 2469 | 598565 | 2735 | 7079 |
DataSet Serialize | 1828 | 2093 | 586200 | 25969 | 29890 |
Entities JSON Serialize | 1719 | 2437 | 325298 | 2500 | 6656 |
以上的测试中,除了Dataset Serialize是使用Dataset作为DTO来序列化和反序列化数据之外,其他的都是使用Entity方式来处理。Xml Serialize表示系统默认的XmlSerializer序列化方式,SoapSerilialize自然是系统默认的SoapFormatter序列化,CustomSerialize则是自定义的序列化方式(目前采用的是自定义序列化+XmlSerializer反序列化结合的方式)。Json Serialization为Teddy的Json优化版本。
测试代码
1
using System;
2
using System.Data;
3
using System.Collections;
4
using System.Configuration;
5
using System.Web;
6
using System.Web.Security;
7
using System.Web.UI;
8
using System.Web.UI.WebControls;
9
using System.Web.UI.WebControls.WebParts;
10
using System.Web.UI.HtmlControls;
11
using Ilungasoft.Framework.Common;
12
using Ilungasoft.Framework.Data.Facade;
13
14
public partial class _Default : System.Web.UI.Page
15
{
16
protected void Page_Load(object sender, EventArgs e)
17
{
18
repeatTime = 10;
19
reportView1.DataSource = DoTest();
20
21
repeatTime = 20;
22
reportView2.DataSource = DoTest();
23
24
repeatTime = 30;
25
reportView3.DataSource = DoTest();
26
27
repeatTime = 40;
28
reportView4.DataSource = DoTest();
29
30
DataBind();
31
}
32
33
private TestReport[] DoTest()
34
{
35
TestReport[] testReports = new TestReport[5];
36
testReports[0] = DoTest1();
37
testReports[1] = DoTest2();
38
testReports[2] = DoTest3();
39
testReports[3] = DoTest4();
40
testReports[4] = DoTest5();
41
42
return testReports;
43
}
44
45
private long time;
46
private DataSet ds;
47
private Order_nbsp_Details_nbsp_Extended[] orderDetails;
48
public string xml;
49
private int repeatTime = 10;
50
51
private TestReport DoTest1()
52
{
53
TestReport testReport = new TestReport();
54
testReport.Title = "Entities Xml Serialize";
55
56
time = System.Environment.TickCount;
57
for (int i = 0; i < repeatTime; i++)
58
orderDetails = DefaultGateway.SelectAll<Order_nbsp_Details_nbsp_Extended>();
59
testReport.ReadDataTime = System.Environment.TickCount - time;
60
61
time = System.Environment.TickCount;
62
for (int i = 0; i < repeatTime; i++)
63
xml = SerializeHelper.SerializeArray(orderDetails);
64
testReport.SerializeTime = System.Environment.TickCount - time;
65
testReport.SerializedXmlSize = xml.Length;
66
67
time = System.Environment.TickCount;
68
for (int i = 0; i < repeatTime; i++)
69
orderDetails = SerializeHelper.Deserialize<Order_nbsp_Details_nbsp_Extended[]>(EntityFactory<Order_nbsp_Details_nbsp_Extended>.GetDynamicEntityType().MakeArrayType(), xml);
70
testReport.DeserializeTime = System.Environment.TickCount - time;
71
72
testReport.TotalRunTime = testReport.ReadDataTime + testReport.SerializeTime + testReport.DeserializeTime;
73
74
return testReport;
75
}
76
77
private TestReport DoTest2()
78
{
79
TestReport testReport = new TestReport();
80
testReport.Title = "Entities Soap Serialize";
81
82
time = System.Environment.TickCount;
83
for (int i = 0; i < repeatTime; i++)
84
orderDetails = DefaultGateway.SelectAll<Order_nbsp_Details_nbsp_Extended>();
85
testReport.ReadDataTime = System.Environment.TickCount - time;
86
87
time = System.Environment.TickCount;
88
for (int i = 0; i < repeatTime; i++)
89
xml = SerializeHelper.SoapSerialize(orderDetails);
90
testReport.SerializeTime = System.Environment.TickCount - time;
91
testReport.SerializedXmlSize = xml.Length;
92
93
time = System.Environment.TickCount;
94
for (int i = 0; i < repeatTime; i++)
95
orderDetails = SerializeHelper.SoapDeserialize<Order_nbsp_Details_nbsp_Extended[]>(xml);
96
testReport.DeserializeTime = System.Environment.TickCount - time;
97
98
testReport.TotalRunTime = testReport.ReadDataTime + testReport.SerializeTime + testReport.DeserializeTime;
99
100
return testReport;
101
}
102
103
private TestReport DoTest3()
104
{
105
TestReport testReport = new TestReport();
106
testReport.Title = "Entities Custom Serialize";
107
108
time = System.Environment.TickCount;
109
for (int i = 0; i < repeatTime; i++)
110
orderDetails = DefaultGateway.SelectAll<Order_nbsp_Details_nbsp_Extended>();
111
testReport.ReadDataTime = System.Environment.TickCount - time;
112
113
time = System.Environment.TickCount;
114
for (int i = 0; i < repeatTime; i++)
115
xml = SerializeHelper.SerializeEntityArray(orderDetails);
116
testReport.SerializeTime = System.Environment.TickCount - time;
117
testReport.SerializedXmlSize = xml.Length;
118
119
time = System.Environment.TickCount;
120
for (int i = 0; i < repeatTime; i++)
121
orderDetails = SerializeHelper.DeserializeEntityArray<Order_nbsp_Details_nbsp_Extended>(xml);
122
testReport.DeserializeTime = System.Environment.TickCount - time;
123
124
testReport.TotalRunTime = testReport.ReadDataTime + testReport.SerializeTime + testReport.DeserializeTime;
125
126
return testReport;
127
}
128
129
private TestReport DoTest4()
130
{
131
TestReport testReport = new TestReport();
132
testReport.Title = "DataSet Serialize";
133
134
time = System.Environment.TickCount;
135
for (int i = 0; i < repeatTime; i++)
136
ds = DefaultGateway.SelectDataSet("select * from [Order Details Extended]");
137
testReport.ReadDataTime = System.Environment.TickCount - time;
138
139
time = System.Environment.TickCount;
140
for (int i = 0; i < repeatTime; i++)
141
{
142
System.IO.MemoryStream ms = new System.IO.MemoryStream();
143
ds.WriteXml(ms);
144
xml = System.Text.UTF8Encoding.UTF8.GetString(ms.ToArray());
145
}
146
testReport.SerializeTime = System.Environment.TickCount - time;
147
testReport.SerializedXmlSize = xml.Length;
148
149
time = System.Environment.TickCount;
150
for (int i = 0; i < repeatTime; i++)
151
{
152
System.IO.MemoryStream ms = new System.IO.MemoryStream(System.Text.UTF8Encoding.UTF8.GetBytes(xml));
153
ds.ReadXml(ms);
154
orderDetails = DefaultGateway.CreateList<Order_nbsp_Details_nbsp_Extended>(ds.Tables[0]);
155
}
156
testReport.DeserializeTime = System.Environment.TickCount - time;
157
158
testReport.TotalRunTime = testReport.ReadDataTime + testReport.SerializeTime + testReport.DeserializeTime;
159
160
return testReport;
161
}
162
163
private TestReport DoTest5()
164
{
165
TestReport testReport = new TestReport();
166
testReport.Title = "Entities JSON Serialize";
167
168
time = System.Environment.TickCount;
169
for (int i = 0; i < repeatTime; i++)
170
orderDetails = DefaultGateway.SelectAll<Order_nbsp_Details_nbsp_Extended>();
171
testReport.ReadDataTime = System.Environment.TickCount - time;
172
173
time = System.Environment.TickCount;
174
for (int i = 0; i < repeatTime; i++)
175
xml = SerializeHelper.JsonSerializeEntityArray(orderDetails);
176
testReport.SerializeTime = System.Environment.TickCount - time;
177
testReport.SerializedXmlSize = xml.Length;
178
179
time = System.Environment.TickCount;
180
for (int i = 0; i < repeatTime; i++)
181
orderDetails = SerializeHelper.JsonDeserializeEntityArray<Order_nbsp_Details_nbsp_Extended>(xml);
182
testReport.DeserializeTime = System.Environment.TickCount - time;
183
184
testReport.TotalRunTime = testReport.ReadDataTime + testReport.SerializeTime + testReport.DeserializeTime;
185
186
return testReport;
187
}
188
}
更多代码我就不列举了,请自行下载下面的源码。
下载
下载测试框架及源码 (本示例源码包含在新版本的Ilungasoft Framework v1.4.4的目录中的dist/Sample5)
小结
本测试示例的目的并不是要终结Dataset作为DTO,尽管Entity作为DTO的性能是可以超越Dataset的,但Teddy觉得,Dataset的性能确实是相当好的,作为一个通用的DTO还是非常适合的(尤其是可以和异构的其他.Net系统方便共享和传递数据)。
补遗:
后续的测试中还发现,无论是XmlSerializer的序列化方式都不够稳定,特别是反序列化时,尤其是对符合类型和数组的序列化。因此,对于大多数基于.Net的程序构架,Teddy还是推荐使用Dataset作为DTO,除非对性能要求非常高时在使用自定义的序列化方式。
4/19:
更新了CustomSerizlize算法,使得其执行时间仅为Dataset的1/2 - 1/10。数据量越大,自定义序列化的优势就越明显。
新增的JSON序列化性能基本和自定义Xml 序列化相当,当数据量较大时,要比自定义Xml序列化方式稍好一点点。
但是,请注意,JSON的序列化后的文本大小只有Dataset的一半,对于需要远程通信的程序来讲,JSON方式将极大的减少需要通信的数据量,因此,JSON方式带来的实际的性能提升可能会更大。
相关文章推荐
- Json.Net 在.Net Core 2.0 中序列化DataSet 问题
- 再接再厉VS 2008 sp1 + .NET 3.5 sp1(4) - Entity Framework(实体框架)之EntityClient, ObjectQuery
- iOS开发——网络篇——JSON和XML,NSJSONSerialization ,NSXMLParser(XML解析器),NSXMLParserDelegate,MJExtension (字典转模型),GDataXML(三方框架解析XML)
- Json.NET使用入门(四)【XML和JSON互转】
- XmlSerializer vs DataContractSerializer: Serialization in Wcf
- 郁闷的.NET 2.0中的Remoting和DataSet的Bug
- .Net 2.0里怎么解析Json啊?
- DataContractSerializer vs XmlSerializer vs DataContractJsonSerializer vs SoapFormatter vs BinaryFormatter 性能测试对比
- .Net: Notices in loading dataset by ReadXml() with options
- 重新注册.Net 2.0(先安装vs后装iis引发的问题)
- .NET中XML与DataSet相互转换
- Sgen.exe: Speed up XmlSerializer's Startup Performance [.NET 2.0, XML Serialization]
- AS与.net的交互——加载web上的xml
- Professional JS(20-JSON Syntax/Serialization/Parse/XMLHttpRequest Object)
- Java调用.NET XML Web Services返回的DataSet
- ADO.NET 2.0 中的新增 DataSet 功能--性能提高44倍?(GridView VS Datagrid)
- JsonHelper Json转xml,Json转DataSet,DataSet转Json
- C# testJsonAsXMLNodeAttribute - XML& json & Collections - XmlNode, XmlElement, XmlAttribute,Dictionary,List
- spark2.0系列《一》—— RDD VS. DataFrame VS. DataSet
- C#中使用JSON.NET实现JSON、XML相互转换