序列化与数据转换 (Serialization & Data Conversion)
最后更新: 2026-07-21
程序集: Snet.Utility / Snet.Core
命名空间: Snet.Utility, Snet.Core.extend
概述
Snet 框架提供了全面的序列化和转换工具集,涵盖 JSON、Protobuf、XML、字节操作、哈希、加密、编码、文件 I/O 和深拷贝。所有方法均为标准 .NET 类型的扩展方法,支持流畅的链式调用。
架构
Snet.Utility.ExtendMethod (静态类, 4000+ 行)
|
+-- System.Text.Json 序列化 (ToJson, ToJsonEntity, JsonFormatting)
+-- Newtonsoft.Json 序列化 (ToNJson, ToNJsonEntity)
+-- Protobuf 序列化 (ToProtobuf, ToProtobufEntity) [protobuf-net]
+-- XML 序列化 (ToXml, ToXmlEntity) [XmlSerializer]
+-- AES 加密 / 解密
+-- SHA256 / SHA1 / MD5 哈希
+-- Base64 编码 / 解码
+-- 字节序 (ReverseBytes, ReverseEndianness, ToNetworkByteOrder)
+-- 结构体封送 (ByteArrayToStructure, StructureToByteArray)
+-- 深拷贝 (DeepCopy 通过 JSON 往返, CopyArray 通过 Array.Copy)
+-- 验证 (IsJson, IsGuid, IsNumber, IsEmail 等)
+-- 类型转换 (ToInt, ToLong, ToDecimal, ToDateTime 等)
+-- 字符串工具 (UrlEncode, HtmlEncode, JoinList 等)
Snet.Utility.ByteHandler (静态类)
+-- 100+ 字节转换方法
+-- Hex/ASCII 转换, CRC 计算, 位操作
+-- 字节拆分/分割, 数组扩展
+-- 整数 <-> byte[] 转换
Snet.Utility.XmlHandler (实例类)
+-- 完整 XML CRUD: XmlSerialize, XmlDeserialize
+-- XmlDocument 操作: Read, Insert, Update, Delete
+-- DataSet/Table 集成
+-- XXE 安全防护 (XmlResolver=null)
+-- 缓存的 XmlSerializer (ConcurrentDictionary)
Snet.Utility.FileHandler (静态类)
+-- FileToString / StringToFile (+ 异步版本)
+-- ConvertToBinary, GetFolderPath
Snet.Core.extend.CoreExtend (静态类)
+-- WriteGetBytes (数值 -> byte[])
+-- ReadGetLength (DataType -> 字节大小)
+-- GetEncoding (EncodingType? -> System.Text.Encoding)
+-- MessageStandard (消息格式标准化)
JSON 序列化 (System.Text.Json)
主要的 JSON 库。Snet.Utility.ExtendMethod 上的扩展方法。
序列化
// 基础: 对象 -> JSON 字符串
string json = obj.ToJson(); // 紧凑格式 (无缩进)
string json = obj.ToJson(formatting: true); // 美化输出
// 使用自定义选项
var options = new JsonSerializerOptions { WriteIndented = true };
string json = obj.ToJson(options);
内部使用的默认选项:
IncludeFields = true-- 除了属性外还序列化字段NumberHandling = AllowNamedFloatingPointLiterals-- 支持 NaN, InfinityEncoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping-- 最小转义,ASCII 可读WriteIndented = false(紧凑) /true(格式化)
反序列化
// 基础: JSON 字符串 -> 类型化对象
var entity = json.ToJsonEntity<MyType>();
// 使用自定义选项
var entity = json.ToJsonEntity<MyType>(new JsonSerializerOptions { ... });
美化输出
string formatted = compactJson.JsonFormatting();
JSON 序列化 (Newtonsoft.Json)
用于向后兼容的传统 JSON 库。
// 序列化
string json = obj.ToNJson(); // 紧凑格式
string json = obj.ToNJson(formatting: true); // 缩进格式
string json = obj.ToNJson(customSettings); // 自定义设置
// 反序列化
var entity = json.ToNJsonEntity<MyType>();
var entity = json.ToNJsonEntity<MyType>(customSettings);
Protobuf 序列化 (protobuf-net)
用于高性能网络传输的二进制序列化。
// 序列化: 对象 -> byte[]
byte[] protoBytes = obj.ToProtobuf();
// 反序列化: byte[] -> 类型化对象
var entity = protoBytes.ToProtobufEntity<MyType>();
要求: 目标类必须使用 [ProtoContract] 和 [ProtoMember(N)] 特性装饰。
在 Snet Core 中的使用:
// AddressValue 数据 -> Protobuf 传输
var dict = new ConcurrentDictionary<string, AddressValue>();
var protoObj = dict.GetSimplifyProtobuf(); // AddressValueSimplifyProtobuf
byte[] wireData = protoObj.ToProtobuf();
// 接收并反序列化
AddressValueSimplifyProtobuf received = wireData.ToProtobufEntity<AddressValueSimplifyProtobuf>();
XML 序列化
ExtendMethod (简单的一行调用)
// 序列化: 对象 -> XML 字符串 (输入为 null 时返回 null)
string? xml = obj.ToXml();
// 反序列化: XML 字符串 -> 对象 (默认 UTF-8)
var entity = xmlString.ToXmlEntity<MyType>();
// 指定编码
var entity = xmlString.ToXmlEntity<MyType>(Encoding.GetEncoding("GB2312"));
XmlHandler (功能完整)
用于复杂 XML 操作的实例类。
| 方法 | 描述 |
|---|---|
XmlSerialize(object, Encoding) |
序列化对象为 XML 字符串 |
XmlDeserialize<T>(string, Encoding?) |
反序列化 XML 字符串为对象 |
CreateXmlDocument() |
创建 XML 文档(无需文件) |
Read(string xmlFile) |
从文件读取 XML 文档 |
Insert(string xmlFile, string nodePath, string element, string? value, IDictionary<string,string>? attrs) |
插入元素/属性 |
Update(string xmlFile, string nodePath, string? value, IDictionary<string,string>? attrs) |
更新元素/属性 |
Delete(string xmlFile, string nodePath, string? attribute) |
删除元素/属性 |
GetDataSet(string xmlFile) |
将 XML 读入 DataSet |
GetTable(string xmlFile, string tableName) |
按名称提取 DataTable |
GetTableCell(string xmlFile, string tableName, int row, int col) |
单单元格值 |
GetNodeValue(string xmlFile, string nodePath) |
通过 XPath 读取节点值 |
ReadXML<T>(string path) |
反序列化 XML 文件为对象 |
WriteXML<T>(string path, T obj, string rootName?, Encoding?) |
序列化对象到 XML 文件 |
SerializeToXmlStr<T>(T obj) |
序列化为 XML 字符串 |
安全性: 所有 XmlDocument 实例均使用 XmlResolver = null 以防止 XXE 攻击。序列化器通过 ConcurrentDictionary<Type, XmlSerializer> 缓存以防止内存泄漏。
字节操作 (ByteHandler)
静态类,包含 100+ 字节级操作方法。
Hex 转换
| 方法 | 签名 | 描述 |
|---|---|---|
HexToBytes |
string -> byte[] |
Hex 字符串转字节数组 |
HexToStr |
byte[] -> string |
字节数组转 Hex 字符串 |
ByteArrayToHexString |
byte[] -> string |
另一种 Hex 格式化 |
StringToByteArray |
string -> byte[] |
Hex 字符串转字节 |
CRC / 校验和
| 方法 | 描述 |
|---|---|
CalculateCrc(byte[]) |
Modbus CRC16 (查表法, XModem 变体, 多项式 0xC0C1) |
calc_crc_16(UInt16 polynomials, byte[] buffer) |
CRC16 自定义多项式变体 |
calc_sum_16(byte[] buffer) |
16 位算术求和校验 |
calc_xor(byte[] buffer) |
XOR 校验 |
CalculateLrc(byte[] data) → byte |
纵向冗余校验 (LRC) |
字节数据操作
| 方法 | 描述 |
|---|---|
ByteDataSplit(byte[] data, int ReserveLocation, int SplitCount) |
按索引和数量分割字节数组 |
ByteListSegmentation(byte[] data, int Segmentation) |
按块大小分割字节数组 |
BoolArrayToByte(bool[]) |
布尔数组转字节 |
ByteToBoolArray(byte[]) |
字节数组转布尔数组 |
AsciiArrayToByteArray(byte[]) |
ASCII 字节转数值 |
ByteArrayToAsciiArray(byte[]) |
数值字节转 ASCII |
BoolOnByteIndex(byte, int index) |
读取指定位置的位 |
SetBoolOnByteIndex(byte, int index, bool) |
设置指定位置的位 |
ArrayExpandToLength(byte[], int) |
填充/截断到指定长度 |
ArraySplitByLength(byte[], int) |
按固定大小分块 |
BytesReverseByWord(byte[]) |
按字反转字节 |
数值转换
| 方法 | 描述 |
|---|---|
IntToBytes(int value) / ByteToInt(byte[] data, bool IsLittleEndian = false) |
Int <-> byte[] |
GetDouble(ushort,ushort,ushort,ushort) |
4 个 ushort -> IEEE 754 double |
GetSingle(ushort,ushort) |
2 个 ushort -> IEEE 754 float |
GetUInt32(ushort,ushort) |
2 个 ushort -> uint32 |
CoreExtend 字节工具 (Snet.Core)
| 方法 | 签名 | 描述 |
|---|---|---|
WriteGetBytes |
object -> byte[] |
数值 (short/ushort/int/uint/long/ulong/double/float) 通过 BitConverter 转字节 |
WriteGetBytes |
string + Encoding -> byte[] |
字符串转编码字节 |
ReadGetLength |
DataType -> ushort |
类型字节大小: Long/Double/Ulong -> 8, Int/Float/Uint -> 4, Short/Ushort -> 2, 其他 -> 0 |
GetEncoding |
EncodingType? -> Encoding |
null -> UTF8, 否则 Encoding.GetEncoding(codePage) |
GetEncoding |
EncodingType -> Encoding |
非空重载 |
GetDefaultEncodingWrite |
ConcurrentDictionary<string,object> + EncodingType? -> ConcurrentDictionary<string,(object,EncodingType?)> |
为写入值附加编码 |
AES 加密
256 位 AES-CBC,通过 System.Security.Cryptography.Aes。
// 加密 (返回 Hex 字符串)
string encrypted = plainText.AESEncrypt(); // 默认密钥/向量
string encrypted = plainText.AESEncrypt(key: myKey, iv: myIV); // 自定义
// 解密 (输入: Hex 字符串, 输出: 明文)
string decrypted = encrypted.AESDecrypt(); // 默认密钥/向量
string decrypted = encrypted.AESDecrypt(key: myKey, iv: myIV); // 自定义
默认密钥: "sDhibwYX7EkqG6b6GfcO3/ft1FBeYb+Gdml4lhKXJ/o=" (SHA256 哈希为 32 字节)
默认向量: "zRDPEQHreJ2d7tANOdGoIQ==" (截断/填充为 16 字节)
哈希
全部返回小写 Hex 字符串。
| 方法 | 输入 | 描述 |
|---|---|---|
ComputeSHA256() |
byte[] / string / FileStream |
SHA256 哈希 |
ComputeSHA1() |
byte[] / string / FileStream |
SHA1 哈希 (不安全) |
ToMD5() |
string |
MD5 哈希 (不安全, 用于文件校验) |
string hash1 = "hello world".ComputeSHA256();
string hash2 = File.OpenRead("file.dat").ComputeSHA256();
string hash3 = bytes.ComputeSHA1();
string hash4 = "data".ToMD5();
Base64
// 编码
string b64 = bytes.ToBase64(); // byte[] -> Base64 字符串
string b64 = "text".UTF8ToBase64(); // 字符串 -> UTF8 字节 -> Base64
// 解码
byte[] bytes = b64Str.Base64ToBytes(); // Base64 字符串 -> byte[]
string text = b64Str.Base64ToUTF8(); // Base64 -> UTF8 字符串
字节序
| 方法 | 描述 |
|---|---|
bytes.ReverseBytes() |
反转字节数组 (大端<->小端) |
value.ReverseEndianness<T>() |
反转值类型字节序 |
array.ReverseEndianness<T>() |
反转数组中每个元素 |
value.ToNetworkByteOrder<T>() |
转换为大端序 (在大端系统上不操作) |
value.FromNetworkByteOrder<T>() |
从大端序转换为主机字节序 |
IsLittleEndian (静态属性) |
BitConverter.IsLittleEndian |
结构体封送
// 字节数组 -> 结构体 (C/C++ 互操作)
var myStruct = byteArray.ByteArrayToStructure<MyStruct>(offset: 0);
// 结构体 -> 字节数组
byte[] bytes = myStruct.StructureToByteArray();
还支持泛型 ToBytes<T>() / ToValue<T>() / ToValueArray<T>(),使用 Marshal.SizeOf 和 GCHandle 钉住。
深拷贝
// 通过 JSON 往返的泛型深拷贝
var copy = original.DeepCopy<MyType>();
// 浅数组拷贝 (值类型 = 深拷贝, 引用类型 = 浅拷贝)
var arr = source.CopyArray();
文件 I/O (FileHandler)
| 方法 | 描述 |
|---|---|
FileToString(string path, Encoding?, bool removeBom) |
读取文件 -> 字符串 (64KB 缓冲区) |
FileToStringAsync(string path, Encoding?, bool removeBom) |
异步读取文件 -> 字符串 |
StringToFile(string path, string content) |
写入字符串 -> 文件 |
StringToFileAsync(string path, string content) |
异步写入字符串 -> 文件 |
ConvertToBinary(string path) |
文件 -> 二进制数据 |
GetFolderPath(string path, bool create) |
提取目录路径,自动创建 |
GetFileName(string path) |
提取含扩展名的文件名 |
验证工具
ExtendMethod 中丰富的验证方法:
| 方法 | 描述 |
|---|---|
IsJson() |
验证 JSON (string / ReadOnlySpan |
IsMatch(pattern) |
正则匹配,可选忽略大小写 |
IsNumber() / IsInteger() |
数值验证 |
IsEmail() |
邮箱格式 |
IsURL() |
URL 格式 |
IsIPv4() / IsIPv6() |
IP 地址验证 |
IsGuid() / IsGuid(out Guid) |
GUID 格式检查 |
IsDateTime() / IsDateTime(out DateTime) |
日期/时间解析 |
IsIDCard() / IsIDCard18() / IsIDCard15() |
中国身份证号验证 |
IsMobilePhoneNumber() |
中国手机号码 |
IsTelePhoneNumber() |
中国座机号码 |
IsZipCode() |
中国邮政编码 |
IsHexadecimal() |
Hex 字符串验证 |
IsLongitude() / IsLatitude() |
地理坐标 |
其他工具
| 类别 | 方法 |
|---|---|
| URL 编码 | UrlEncode(), UrlDecode() |
| HTML 编码 | HtmlEncode(), HtmlDecode() |
| 字符串拼接 | JoinList<T>(split, prefix, suffix) |
| SQL 助手 | ToSqlIn(), JoinSqlIn<T>() |
| GUID 助手 | ToUpperNString(), ToLowerNString(), ToNString() |
| DateTime 格式化 | ToLongDate(), ToDateString(), ToDateTimeString(), ToShortDateTimeString(), GetDate(), GetDateDetails() |
| Unix 时间戳 | DateTime.ToInt() (转 Unix 秒), int.ToDateTime() (从 Unix 秒转换) |
| 对象比较 | Comparer<T>(other, ignoreProperties?) -- 深度对象差异比较 |
| 枚举助手 | EnumToList<T>(), GetDescription(), EnumValueToEnumObj<T>(), EnumKeyToEnumObj<T>() |
| 类型转换 | ToInt(), ToLong(), ToDecimal(), ToDouble(), ToDateTime(), ToULong(), ToUInt() |
| 字节数组 | ToBytes() (结构体 / 字符串), ToValue<T>(), ToUTF8String(), ToEncodeString() |
| 延时 | DelayUs(double) / DelayUs(int) -- 微秒级自旋等待 |
代码示例
序列化往返 (JSON)
var address = new Address("Line1", details, DateTime.Now);
// JSON 往返
string json = address.ToJson(formatting: true);
Address? restored = json.ToJsonEntity<Address>();
// Protobuf 往返
byte[] proto = address.ToProtobuf();
Address protoRestored = proto.ToProtobufEntity<Address>();
// XML 往返
string? xml = address.ToXml();
Address? xmlRestored = xml.ToXmlEntity<Address>();
// Newtonsoft 往返
string njson = address.ToNJson(formatting: true);
Address? nRestored = njson.ToNJsonEntity<Address>();
字节转换管道
// 数值 -> 字节 (用于 PLC 写入)
short value = 1234;
byte[] bytes = ((object)value).WriteGetBytes(); // [0xD2, 0x04] (小端序)
// 字节 -> Hex 字符串
string hex = ByteHandler.ByteArrayToHexString(bytes); // "D204"
// Hex 字符串 -> 字节
byte[] fromHex = ByteHandler.HexToBytes("D204");
// Modbus CRC
byte[] frame = [0x01, 0x03, 0x00, 0x00, 0x00, 0x01];
ushort crc = ByteHandler.CalculateCrc(frame); // CRC16 结果
// 字符串 -> 编码字节 -> Hex
string text = "Hello Snet";
Encoding gb2312 = ((EncodingType?)EncodingType.GB2312).GetEncoding();
byte[] encodedBytes = text.WriteGetBytes(gb2312);
加密与哈希
// AES 加密/解密
string encrypted = "敏感数据".AESEncrypt();
string decrypted = encrypted.AESDecrypt();
// decrypted == "敏感数据"
// SHA256
string fileHash = File.OpenRead("config.json").ComputeSHA256();
// MD5 (文件校验)
string checksum = "hello".ToMD5();
深拷贝与比较
// 深拷贝
var cloned = originalAddress.DeepCopy<Address>();
// 深度比较 (忽略指定属性)
var (isEqual, differences) = address1.Comparer(address2, new[] { "Time", "CreationTime" });
if (!isEqual)
{
foreach (var diff in differences)
Console.WriteLine($"{diff.PropertyName}: {diff.Object1Value} != {diff.Object2Value}");
}
