C# 序列化详解,xml序列化,json序列化对比
本文讲讲一些纯技术的东西。并且讲讲一些原理性的东西,和一般的百度的文章不一致,如果你对序列化不清楚,绝对可以很有收获。
ok,我们先建一个控制台项目:
安装 Newtonsoft.Json 组件
ok,安装完成之后,我们来讲讲序列化的本质:
为什么需要序列化?
要理解这个问题很关键。很多事就会豁然开朗,与其讲为什么序列化,不如我们先来看看一个例子:
我们存储了一条字符串的数据到文件
我们可能会这么写
public static void SaveString(string str )
{
using(System.IO.StreamWriter sw = new System.IO.StreamWriter( "123.txt", false, Encoding.Default ))
{
sw.Write( str );
}
}
然后读取你存储的数据时候,会这么读
public static string ReadString( )
{
using (System.IO.StreamReader sr = new System.IO.StreamReader( "123.txt", Encoding.Default ))
{
return sr.ReadToEnd( );
}
}
其实这里的代码已经实现了最基本的序列化功能。如果你觉得存储string很简单,那么来存储一个int[]数组把。将整个数据存储到文件,然后读取加载
public static void SaveIntArray( int[] value )
{
byte[] buffer = new byte[value.Length * 4];
for (int i = 0; i < value.Length; i++)
{
BitConverter.GetBytes( value[i] ).CopyTo( buffer, i * 4 );
} System.IO.File.WriteAllBytes( "1234.txt", buffer );
}
然后加载的步骤是
public static int[] ReadIntArray( )
{
byte[] buffer = System.IO.File.ReadAllBytes( "1234.txt" ); int[] value = new int[buffer.Length / 4];
for (int i = 0; i < value.Length; i++)
{
value[i] = BitConverter.ToInt32( buffer, i * 4 );
}
return value;
}
上述的两个示例展示了最基本的序列化和反序列化操作。我们实现序列化和反序列通常是用于写入文件,加载数据,发送到网络,从网络接收数据。
这个就是我们最大的需求了。
实际复杂的数据
比如我们有一串复杂的数据,需要写文件,或是收发网络,写文件和收发网络的本质是读写byte[]数组。而byte[]数组和string是几乎等效的,可以相互转换。很多的文件写入,或是网络收发都是支持支持string的
所以我们的序列化和反序列化的本质就是实际的数据和string的相互转换。
比如这个数据对象
public class Account
{
public string UserName { get; set; }
public string Password { get; set; }
public int Age { get; set; }
public string Phone { get; set; }
public double Stature { get; set; }
}
要把这个数据对象转换成string,然后支持转换回来,应该怎么操作呢?
接下来就是干货了
XML序列化及,反序列化
直接上代码:
public class Account
{
public string UserName { get; set; }
public string Password { get; set; }
public int Age { get; set; }
public string Phone { get; set; }
public double Stature { get; set; } public string toXml( )
{
System.Xml.Linq.XElement element = new System.Xml.Linq.XElement( "Account" );
element.SetElementValue( nameof( UserName ), UserName );
element.SetElementValue( nameof( Password ), Password );
element.SetElementValue( nameof( Age ), Age.ToString() );
element.SetElementValue( nameof( Phone ), Phone );
element.SetElementValue( nameof( Stature ), Stature.ToString( ) ); return element.ToString( );
} public void LoadByXml( string data )
{
System.Xml.Linq.XElement element = System.Xml.Linq.XElement.Parse( data );
UserName = element.Element( nameof( UserName ) ).Value;
Password = element.Element( nameof( Password ) ).Value;
Age = int.Parse( element.Element( nameof( Age ) ).Value );
Phone = element.Element( nameof( Phone ) ).Value;
Stature = double.Parse( element.Element( nameof( Stature ) ).Value );
}
}
我们改造一下就可以了,现在这个类支持了序列化及反序列了,我们看看控制台输出了什么?
static void Main( string[] args )
{ Account account = new Account( )
{
UserName = "张三",
Password = "123456",
Age = 25,
Phone = "12345678901",
Stature = 170.2d
}; Console.WriteLine( account.toXml( ) );
Console.ReadLine( );
}
看看控制台:
输出了我们想要的字符串信息。好了,接下来,我们看看JSON格式的数据
JSON序列化及反序列化
json因为库的方便性,所以不需要写多余的代码了
static void Main( string[] args )
{ Account account = new Account( )
{
UserName = "张三",
Password = "123456",
Age = 25,
Phone = "12345678901",
Stature = 170.2d
}; //Console.WriteLine( account.toXml( ) ); Console.WriteLine( JObject.FromObject( account ).ToString( ) ); Console.ReadLine( );
}
输出
灵活的操作
现在有个小问题,密码部分的内容我不想支持序列化,或是换句话说,密码的信息在序列化的时候忽略。那么类改成下面即可
public class Account
{
public string UserName { get; set; } [Newtonsoft.Json.JsonIgnore]
public string Password { get; set; }
public int Age { get; set; }
public string Phone { get; set; }
public double Stature { get; set; } public string toXml( )
{
System.Xml.Linq.XElement element = new System.Xml.Linq.XElement( "Account" );
element.SetElementValue( nameof( UserName ), UserName );
//element.SetElementValue( nameof( Password ), Password );
element.SetElementValue( nameof( Age ), Age.ToString() );
element.SetElementValue( nameof( Phone ), Phone );
element.SetElementValue( nameof( Stature ), Stature.ToString( ) ); return element.ToString( );
} public void LoadByXml( string data )
{
System.Xml.Linq.XElement element = System.Xml.Linq.XElement.Parse( data );
UserName = element.Element( nameof( UserName ) ).Value;
//Password = element.Element( nameof( Password ) ).Value;
Age = int.Parse( element.Element( nameof( Age ) ).Value );
Phone = element.Element( nameof( Phone ) ).Value;
Stature = double.Parse( element.Element( nameof( Stature ) ).Value );
}
}
这样就忽略了密码的xml序列化和json的序列化
xml支持子元素和特性,内容存储上更加的丰富,json更加直接一点,内容精简一点,json也可以写成上述的xml灵活的方法,这样就支持任意格式对象的序列化和反序列化了。
public class Account
{
public string UserName { get; set; } [Newtonsoft.Json.JsonIgnore]
public string Password { get; set; }
public int Age { get; set; }
public string Phone { get; set; }
public double Stature { get; set; } public string toXml( )
{
System.Xml.Linq.XElement element = new System.Xml.Linq.XElement( "Account" );
element.SetElementValue( nameof( UserName ), UserName );
//element.SetElementValue( nameof( Password ), Password );
element.SetElementValue( nameof( Age ), Age.ToString() );
element.SetElementValue( nameof( Phone ), Phone );
element.SetElementValue( nameof( Stature ), Stature.ToString( ) ); return element.ToString( );
} public void LoadByXml( string data )
{
System.Xml.Linq.XElement element = System.Xml.Linq.XElement.Parse( data );
UserName = element.Element( nameof( UserName ) ).Value;
//Password = element.Element( nameof( Password ) ).Value;
Age = int.Parse( element.Element( nameof( Age ) ).Value );
Phone = element.Element( nameof( Phone ) ).Value;
Stature = double.Parse( element.Element( nameof( Stature ) ).Value );
} public string toJson( )
{
JObject json = new JObject( );
//json.Add( nameof( Password ), new JValue( Password ) );
json.Add( nameof( UserName ), new JValue( UserName ) );
json.Add( nameof( Age ), new JValue( Age ) );
json.Add( nameof( Phone ), new JValue( Phone ) );
json.Add( nameof( Stature ), new JValue( Stature ) ); return json.ToString( );
} public void LoadByJson(string data )
{
JObject json = JObject.Parse( data );
UserName = json[nameof( UserName )].Value<string>( );
//Password = json[nameof( Password )].Value<string>( );
Age = json[nameof( Age )].Value<int>( );
Phone = json[nameof( Phone )].Value<string>( );
Stature = json[nameof( Stature )].Value<double>( );
}
}
这样也能实现任意的序列化操作,甚至针对其中某个属性进行加密解密都可以。
性能对比(具体时间取决于电脑性能,我的cpu : i5-4590 内存 ddr3-1600)
两种序列化都有适合的场景,此处演示下序列化1W次的性能对比,看看性能差异
static void Main( string[] args )
{ Account account = new Account( )
{
UserName = "张三",
Password = "123456",
Age = 25,
Phone = "12345678901",
Stature = 170.2d
}; DateTime start = DateTime.Now; for (int i = 0; i < 10000; i++)
{
string value = account.toXml( );
;
} Console.WriteLine( "Time:" + (DateTime.Now - start).TotalMilliseconds );
start = DateTime.Now; for (int i = 0; i < 10000; i++)
{
string value = JObject.FromObject( account ).ToString( );
;
} Console.WriteLine( "Time:" + (DateTime.Now - start).TotalMilliseconds );
start = DateTime.Now; for (int i = 0; i < 10000; i++)
{
string value = account.toJson( );
;
}
Console.WriteLine( "Time:" + (DateTime.Now - start).TotalMilliseconds ); Console.ReadLine( );
}
第一次运行:
第二次运行:
第三次运行:
接下来加上解析部分
{ Account account = new Account( )
{
UserName = "张三",
Password = "123456",
Age = 25,
Phone = "12345678901",
Stature = 170.2d
}; DateTime start = DateTime.Now; for (int i = 0; i < 10000; i++)
{
string value = account.toXml( );
Account account1 = new Account( );
account1.LoadByXml( value );
} Console.WriteLine( "Time:" + (DateTime.Now - start).TotalMilliseconds );
start = DateTime.Now; for (int i = 0; i < 10000; i++)
{
string value = JObject.FromObject( account ).ToString( );
Account account1 = JObject.Parse( value ).ToObject<Account>( );
} Console.WriteLine( "Time:" + (DateTime.Now - start).TotalMilliseconds );
start = DateTime.Now; for (int i = 0; i < 10000; i++)
{
string value = account.toJson( );
Account account1 = new Account( );
account1.LoadByJson( value );
}
Console.WriteLine( "Time:" + (DateTime.Now - start).TotalMilliseconds ); Console.ReadLine( );
}
我们再来看看运行结果:
第二次运行结果:
第三次结果:
终极性能PK
如果我们自己来写json的序列化呢?
public class Account
{
public string UserName { get; set; } [Newtonsoft.Json.JsonIgnore]
public string Password { get; set; }
public int Age { get; set; }
public string Phone { get; set; }
public double Stature { get; set; } public string toXml( )
{
System.Xml.Linq.XElement element = new System.Xml.Linq.XElement( "Account" );
element.SetElementValue( nameof( UserName ), UserName );
//element.SetElementValue( nameof( Password ), Password );
element.SetElementValue( nameof( Age ), Age.ToString() );
element.SetElementValue( nameof( Phone ), Phone );
element.SetElementValue( nameof( Stature ), Stature.ToString( ) ); return element.ToString( );
} public void LoadByXml( string data )
{
System.Xml.Linq.XElement element = System.Xml.Linq.XElement.Parse( data );
UserName = element.Element( nameof( UserName ) ).Value;
//Password = element.Element( nameof( Password ) ).Value;
Age = int.Parse( element.Element( nameof( Age ) ).Value );
Phone = element.Element( nameof( Phone ) ).Value;
Stature = double.Parse( element.Element( nameof( Stature ) ).Value );
} public string toJson( )
{
JObject json = new JObject( );
//json.Add( nameof( Password ), new JValue( Password ) );
json.Add( nameof( UserName ), new JValue( UserName ) );
json.Add( nameof( Age ), new JValue( Age ) );
json.Add( nameof( Phone ), new JValue( Phone ) );
json.Add( nameof( Stature ), new JValue( Stature ) ); return json.ToString( );
} public void LoadByJson(string data )
{
JObject json = JObject.Parse( data );
UserName = json[nameof( UserName )].Value<string>( );
//Password = json[nameof( Password )].Value<string>( );
Age = json[nameof( Age )].Value<int>( );
Phone = json[nameof( Phone )].Value<string>( );
Stature = json[nameof( Stature )].Value<double>( );
} public string toMyJson( )
{
StringBuilder sb = new StringBuilder( );
sb.Append( "{" );
sb.Append( Environment.NewLine );
sb.Append( $" \"{nameof( UserName )}\":" );
sb.Append( $"\"{ UserName.Replace( "\"", "\\\"" )}\"," );
sb.Append( Environment.NewLine );
sb.Append( $" \"{nameof( Password )}\":" );
sb.Append( $"\"{ Password.Replace( "\"", "\\\"" ) }\"," );
sb.Append( Environment.NewLine );
sb.Append( $" \"{nameof( Age )}\":" );
sb.Append( $"{Age}," );
sb.Append( Environment.NewLine );
sb.Append( $" \"{nameof( Phone )}\":" );
sb.Append( $"\"{ Phone.Replace( "\"", "\\\"" )}\"," );
sb.Append( Environment.NewLine );
sb.Append( $" \"{nameof( Stature )}\":" );
sb.Append( $"{Stature}," );
sb.Append( Environment.NewLine );
sb.Append( "}" );
return sb.ToString( );
}
}
上述的方法 toMyJson 就是我们所写的一个方法名称,这个方法会主动进行序列化,里面也考虑了,如果字符串数据带有"的情况,需要进行替换 \" 的情况,我们单独运行这个序列化的方法10000次
所以关于性能,可以大致做个参考
以上的结果只能参照一下,写法上大家可以根据自己的需求来选择,性能上肯定会有所差别的。感谢阅读:
C# 序列化详解,xml序列化,json序列化对比的更多相关文章
- wp8.1 Study11:APP里文件读写和使用XML和Json序列化
一.文件读写 1.基本操作(使用FileIO API) 这个方法在上一个stduy已经学过,那么贴出来复习下,代码如下: private async void writeTextToLocalStor ...
- xml 和 json 序列化忽略字段
xml 和 json 序列化忽略字段: @JsonIgnore @XmlTransient
- Log4j2详解——XML配置详解
Log4j2详解--XML配置详解 找到了个很详细的文章链接 https://www.jianshu.com/p/bfc182ee33db
- XML与JSON的对比
XML与JSON的对比 1.各自定义 XML 扩展标记语言 (Extensible Markup Language, XML) ,用于标记电子文件使其具有结构性的标记语言,可以用来标记数据.定义数据类 ...
- Django Rest Framework(2)-----序列化详解(serializers)
REST framework中的序列化类与Django的Form和ModelForm类非常相似.我们提供了一个Serializer类,它提供了一种强大的通用方法来控制响应的输出,以及一个ModelSe ...
- Xml、Json序列化
Xml序列化: public class XmlHelper { private static string XmlPath = Path.Combine(AppDomain.CurrentDomai ...
- XML和JSON序列化以及反序列化
1.将文件保存序列化至文档中,然后再读取: //首先创建可序列化的实体类 [Serializable] public class Message { public string Name { get; ...
- 跟我一起学WCF(7)——WCF数据契约与序列化详解
一.引言 在前面博文介绍到,WCF的契约包括操作契约.数据契约.消息契约和错误契约,前面一篇博文已经结束了操作契约的介绍,接下来自然就是介绍数据契约了.所以本文要分享的内容就是数据契约. 二.数据契约 ...
- rest_framework之序列化详解 06
拿到所有的角色数据 1.urls.py 2.models.py 假设只有3个角色 3.views.py from api import models import json json只能序列化pyt ...
随机推荐
- 总结工作中常用的PHP代码
[目录] ◆PHP常用的代码 ◆HTML常用代码 [值传递 和 引用传递] [单例模式] [魔术常量] [代码调试(自定义一个简单的debug函数)] [thinkphp多表查询] [获取客户端IP地 ...
- cocos代码研究(18)Widget子类Slider学习笔记
理论基础 滑动条控件. 代码实践 实例: // Create the slider Slider* slider = Slider::create(); slider->loadBarTextu ...
- SpringBoot 通过自定义注解实现AOP切面编程实例
一直心心念的想写一篇关于AOP切面实例的博文,拖更了许久之后,今天终于着手下笔将其完成. 基础概念 1.切面(Aspect) 首先要理解‘切’字,需要把对象想象成一个立方体,传统的面向对象变成思维,类 ...
- Educational Codeforces Round 59 Solution
A. Digits Sequence Dividing 签. #include <bits/stdc++.h> using namespace std; #define N 1010 ch ...
- Python: 矩阵与线性代数运算
需要执行矩阵和线性代数运算,比如矩阵乘法.寻找行列式.求解线性方程组等等. 矩阵类似于3.9 小节中数组对象,但是遵循线性代数的计算规则.下面的一个例子展示了矩阵的一些基本特性: >>&g ...
- Python笔记 #08# NumPy: Statistic Basis
数据分析的基本步骤: 了解你的数据(get to know your data), 做一些统计学处理(像僵尸一样盯着数字不会带给你任何灵感!) 实现可视化(get a better feeling f ...
- Django使用本地css/js文件
Django使用本地css/js文件 在manager.py同层级下创建static文件夹, 里面放上css , js, images等文件或者文件夹 我的文件夹层级 然后只需在settings.py ...
- 20145326 《Java程序设计》第6周学习总结
20145326 <Java程序设计>第6周学习总结 教材学习内容总结 第十章 一.使用InputStream与OutputStream 1.串流设计的概念 想活用输入/输出API,一定要 ...
- DirectX9.0c SDK学习笔记(一)
Direct9.0c SDK中提供了一个叫DXviewer的*.x格式文件查看器的源码,代码给出了基于DXUT框架的模型显示接口使用方法, 对于我想编写一个动作捕捉的上位程序是大有助益的. 我的想法是 ...
- ubuntu18.04下挂载网络文件系统失败【学习笔记】
作者:庄泽彬(欢迎转载,请注明作者) PC: ubuntu18.04 说明: 之前ubuntu16.04下搭建的环境,开发板挂载网络文件系统是ok的,但是换到ubuntu18.04在启动的时候 ...