想必大家在项目中都接触过 JSON 或者 XML 吧,为了将对象在网络上传输或者将其持久化必须将其序列化为一个字符串然后进行后续操作。常见的就是将其序列化成 JSON 或者 XML 。
大家在项目中应该都看到过这样的工具类 例如 ***XmlHelper、***JsonHelper 等,没错这一些助手类会帮助我们重复造轮子。既然是组件并且还是是开源的必须考虑每个功能的后续可扩展性以及易用性。
ISerializer 序列化者接口
1 using System; 2 3 namespace Wlitsoft.Framework.Common.Abstractions.Serialize 4 { 5 /// <summary> 6 /// 序列化者接口。 7 /// </summary> 8 public interface ISerializer 9 { 10 /// <summary> 11 /// 获取序列化类型。 12 /// </summary> 13 SerializeType SerializeType { get; } 14 15 /// <summary> 16 /// 将一个对象序列化成一个字符串。 17 /// </summary> 18 /// <param name="obj">要序列化的对象。</param> 19 /// <returns>序列化后的字符串。</returns> 20 string Serialize(object obj); 21 22 /// <summary> 23 /// 将一个字符串反序列化为一个对象。 24 /// </summary> 25 /// <param name="objType">要反序序列化的对象类型。</param> 26 /// <param name="str">要反序列化的字符串。</param> 27 /// <returns>反序列化得到的对象。</returns> 28 object Deserialize(Type objType, string str); 29 30 /// <summary> 31 /// 将一个字符串反序列化为一个对象。 32 /// </summary> 33 /// <param name="str">要反序列化的字符串。</param> 34 /// <returns>反序列化得到的对象。</returns> 35 T Deserialize<T>(string str); 36 } 37 }
该接口很简单就一个属性标示序列化类型、序列化方法、反序列化方法。
SerializeType 序列化类型
1 namespace Wlitsoft.Framework.Common.Abstractions.Serialize 2 { 3 /// <summary> 4 /// 序列化类型。 5 /// </summary> 6 public enum SerializeType 7 { 8 /// <summary> 9 /// Xml。 10 /// </summary> 11 Xml, 12 13 /// <summary> 14 /// Json。 15 /// </summary> 16 Json 17 } 18 }
一个枚举标识使用哪种序列化方式。
类型有了那对应的原始的实现肯定少不了。
- JsonSerializer Json 序列化/反序列化。
1 using System; 2 using System.IO; 3 using System.Runtime.Serialization.Json; 4 using System.Text; 5 using Wlitsoft.Framework.Common.Abstractions.Serialize; 6 using Wlitsoft.Framework.Common.Exception; 7 8 namespace Wlitsoft.Framework.Common.Serialize 9 { 10 /// <summary> 11 /// Json 序列化/反序列化。 12 /// </summary> 13 public class JsonSerializer : ISerializer 14 { 15 #region ISerializer 成员 16 17 /// <summary> 18 /// 获取序列化类型。 19 /// </summary> 20 public SerializeType SerializeType { get; } = SerializeType.Json; 21 22 /// <summary> 23 /// 将一个对象序列化成一个字符串。 24 /// </summary> 25 /// <param name="obj">要序列化的对象。</param> 26 /// <returns>序列化后的字符串。</returns> 27 public string Serialize(object obj) 28 { 29 #region 参数校验 30 31 if (obj == null) 32 throw new ObjectNullException(nameof(obj)); 33 34 #endregion 35 36 using (var ms = new MemoryStream()) 37 { 38 new DataContractJsonSerializer(obj.GetType()).WriteObject(ms, obj); 39 return Encoding.UTF8.GetString(ms.ToArray()); 40 } 41 42 } 43 44 /// <summary> 45 /// 将一个字符串反序列化为一个对象。 46 /// </summary> 47 /// <param name="objType">要反序序列化的对象类型。</param> 48 /// <param name="str">要反序列化的字符串。</param> 49 /// <returns>反序列化得到的对象。</returns> 50 public object Deserialize(Type objType, string str) 51 { 52 #region 参数校验 53 54 if (objType == null) 55 throw new ObjectNullException(nameof(objType)); 56 57 if (string.IsNullOrEmpty(str)) 58 throw new StringNullOrEmptyException(nameof(str)); 59 60 #endregion 61 62 using (var ms = new MemoryStream(Encoding.UTF8.GetBytes(str))) 63 { 64 return new DataContractJsonSerializer(objType).ReadObject(ms); 65 } 66 } 67 68 /// <summary> 69 /// 将一个字符串反序列化为一个对象。 70 /// </summary> 71 /// <param name="str">要反序列化的字符串。</param> 72 /// <returns>反序列化得到的对象。</returns> 73 public T Deserialize<T>(string str) 74 { 75 #region 参数校验 76 77 if (string.IsNullOrEmpty(str)) 78 throw new StringNullOrEmptyException(nameof(str)); 79 80 #endregion 81 82 return (T)this.Deserialize(typeof(T), str); 83 } 84 85 #endregion 86 } 87 }
JsonSerializer
- XmlSerializer Xml 序列化/反序列化。
1 using System; 2 using System.IO; 3 using System.Text; 4 using System.Xml; 5 using System.Xml.Serialization; 6 using Wlitsoft.Framework.Common.Abstractions.Serialize; 7 using Wlitsoft.Framework.Common.Exception; 8 9 namespace Wlitsoft.Framework.Common.Serialize 10 { 11 /// <summary> 12 /// Xml 序列化/反序列化。 13 /// </summary> 14 public class XmlSerializer : ISerializer 15 { 16 #region ISerializer 成员 17 18 /// <summary> 19 /// 获取序列化类型。 20 /// </summary> 21 public SerializeType SerializeType { get; } = SerializeType.Xml; 22 23 /// <summary> 24 /// 将一个对象序列化成一个字符串。 25 /// </summary> 26 /// <param name="obj">要序列化的对象。</param> 27 /// <returns>序列化后的字符串。</returns> 28 public string Serialize(object obj) 29 { 30 #region 参数校验 31 32 if (obj == null) 33 throw new ObjectNullException(nameof(obj)); 34 35 #endregion 36 37 System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(obj.GetType()); 38 39 //去除默认的命名空间声明。 40 XmlSerializerNamespaces xmlNamespaces = new XmlSerializerNamespaces(); 41 xmlNamespaces.Add("", ""); 42 43 XmlWriterSettings settings = new XmlWriterSettings(); 44 settings.OmitXmlDeclaration = true; 45 settings.Indent = true; 46 settings.NewLineChars = "\r\n"; 47 settings.IndentChars = " "; 48 49 MemoryStream outStream = new MemoryStream(); 50 using (XmlWriter writer = XmlWriter.Create(outStream, settings)) 51 { 52 serializer.Serialize(writer, obj, xmlNamespaces); 53 } 54 55 outStream.Position = 0; 56 using (StreamReader reader = new StreamReader(outStream)) 57 { 58 return reader.ReadToEnd(); 59 } 60 } 61 62 /// <summary> 63 /// 将一个字符串反序列化为一个对象。 64 /// </summary> 65 /// <param name="objType">要反序序列化的对象类型。</param> 66 /// <param name="str">要反序列化的字符串。</param> 67 /// <returns>反序列化得到的对象。</returns> 68 public object Deserialize(Type objType, string str) 69 { 70 #region 参数校验 71 72 if (objType == null) 73 throw new ObjectNullException(nameof(objType)); 74 75 if (string.IsNullOrEmpty(str)) 76 throw new StringNullOrEmptyException(nameof(str)); 77 78 #endregion 79 80 System.Xml.Serialization.XmlSerializer mySerializer = new System.Xml.Serialization.XmlSerializer(objType); 81 using (MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(str))) 82 { 83 using (StreamReader sr = new StreamReader(ms)) 84 { 85 return mySerializer.Deserialize(sr); 86 } 87 } 88 } 89 90 /// <summary> 91 /// 将一个字符串反序列化为一个对象。 92 /// </summary> 93 /// <param name="str">要反序列化的字符串。</param> 94 /// <returns>反序列化得到的对象。</returns> 95 public T Deserialize<T>(string str) 96 { 97 #region 参数校验 98 99 if (string.IsNullOrEmpty(str)) 100 throw new StringNullOrEmptyException(nameof(str)); 101 102 #endregion 103 104 return (T)this.Deserialize(typeof(T), str); 105 } 106 107 #endregion 108 109 } 110 }
XmlSerializer
接口有了,对应的原生实现也有了,那咋用呢,还有我要不想用原生的Json 序列化方式咋办比如想用 JSON.Net 别急继续往下 See。
SerializerFactory 序列化工厂
把它定义成工厂确实有些牵强但是没有想到很好的名称 那就暂时先就叫工厂吧。它主要存储所有的序列化者对象实例、可以获取实例、亦可以重新设置实例。下面只列出方法签名。
/// <summary> /// 获取一个 <see cref="ISerializer"/> 的实例。 /// </summary> /// <param name="type">序列化类型。</param> /// <returns>一个 <see cref="ISerializer"/> 类型的对象实例。</returns> public ISerializer GetSerializer(SerializeType type)
/// <summary> /// 获取一个 <see cref="ISerializer"/> 的实例。 /// </summary> /// <param name="type">序列化类型。</param> /// <returns>一个 <see cref="ISerializer"/> 类型的对象实例。</returns> public ISerializer GetSerializer(SerializeType type)
现在可以使用了,等下 还没完。。。 为了更便于使用它们 将其做成 扩展方法。
ObjectExtensions 对象扩展方法静态类。
1 /// <summary> 2 /// 将 json 字符串转换为指定类型的对象表示形式。 3 /// </summary> 4 /// <typeparam name="T">要转换成的对象类型。</typeparam> 5 /// <param name="json">json 字符串。</param> 6 /// <returns>转换完后的 JSON 对象。</returns> 7 public static T ToJsonObject<T>(this string json) 8 { 9 #region 参数校验 10 11 if (string.IsNullOrEmpty(json)) 12 throw new StringNullOrEmptyException(nameof(json)); 13 14 #endregion 15 16 ISerializer serializer = GlobalConfig.SerializerFactory.GetJsonSerializer(); 17 return serializer.Deserialize<T>(json); 18 }
1 /// <summary> 2 /// 将给定 XML 字符串(<see paracref="xml"/>)转换为指定类型的对象表示形式。 3 /// </summary> 4 /// <typeparam name="T">要转换成的对象类型。</typeparam> 5 /// <param name="xml">json 字符串。</param> 6 /// <returns>转换完后的 Xml 对象。</returns> 7 public static T ToXmlObject<T>(this string xml) 8 { 9 #region 参数校验 10 11 if (string.IsNullOrEmpty(xml)) 12 throw new StringNullOrEmptyException(nameof(xml)); 13 14 #endregion 15 16 ISerializer serializer = GlobalConfig.SerializerFactory.GetXmlSerializer(); 17 return serializer.Deserialize<T>(xml); 18 }
StringExtensions 字符串类型扩展方法静态类。
1 /// <summary> 2 /// 将给定对象(<paramref name="obj"/>)转换成 JSON 字符串的表示形式。 3 /// </summary> 4 /// <param name="obj">准备进行转换的对象。</param> 5 /// <returns>转换后生成的 JSON 字符串。</returns> 6 public static string ToJsonString(this object obj) 7 { 8 #region 参数校验 9 10 if (obj == null) 11 throw new ObjectNullException(nameof(obj)); 12 13 #endregion 14 15 ISerializer serializer = GlobalConfig.SerializerFactory.GetJsonSerializer(); 16 return serializer.Serialize(obj); 17 }
1 /// <summary> 2 /// 将给定 XML 字符串(<see paracref="xml"/>)转换为指定类型的对象表示形式。 3 /// </summary> 4 /// <typeparam name="T">要转换成的对象类型。</typeparam> 5 /// <param name="xml">json 字符串。</param> 6 /// <returns>转换完后的 Xml 对象。</returns> 7 public static T ToXmlObject<T>(this string xml) 8 { 9 #region 参数校验 10 11 if (string.IsNullOrEmpty(xml)) 12 throw new StringNullOrEmptyException(nameof(xml)); 13 14 #endregion 15 16 ISerializer serializer = GlobalConfig.SerializerFactory.GetXmlSerializer(); 17 return serializer.Deserialize<T>(xml); 18 }
关于扩展性
回到刚才那个问题,如果我不想用原生的 Json 序列化方式咋办,难不成字符串扩展以及对象扩展这些方法都用不了了吗。别急继续往下看。
Common.JsonNet.JsonSerializer 公共类库 Json.Net 组件序列化者。
该项目中 JsonNetJsonSerializer 实现了 ISerializer 接口,也就是说这个类有序列化和反序列化的能力,那类有了怎么用呢。
当然你可以直接 new 一个 JsonNetJsonSerializer 的实例 然后使用。但是这样的话就有点本末倒置了。
GlobalConfig 全局配置静态类
这个类中后续会有好多属性 可以修改 Common 包内部的一些实现方式。
比如:将 Common 包中原生的 Json 序列化实现用 JSON.Net 取缔只需要 在 网站的 Startup 或者 控制台中的 静态构造方法中写入下面一行代码即可。
1 GlobalConfig.SerializerFactory.SetSerializer(SerializeType.Json,new JsonNetJsonSerializer());
未完待续。
下篇预告:一个技术汪的开源梦 —— 基于 .Net Core 的公共组件之 Http 请求客户端。