序列化详解
1、序列化概念
(1)核心作用
- 序列化:将对象转换为可存储/传输的格式(如二进制、JSON、XML),用于数据持久化(保存到文件/数据库)、网络传输(Socket通信)等场景。
- 反序列化:将序列化数据还原为对象实例。
(2)必需标记
- 类需添加
[Serializable] 特性,否则抛出 SerializationException:
[Serializable]
public class Person {public string Name { get; set; }public int Age { get; set; }
}
- 排除字段:用
[NonSerialized] 标记不序列化的字段。
️ 2、序列化常用方式
(1)二进制序列化(高效紧凑)
- 优点:速度快,数据体积小。
- 缺点:仅限 .NET 平台,安全性较低(易受恶意数据攻击)。
using System.Runtime.Serialization.Formatters.Binary;
BinaryFormatter formatter = new BinaryFormatter();
using (FileStream stream = new FileStream("data.dat", FileMode.Create)) {formatter.Serialize(stream, person);
}
using (FileStream stream = new FileStream("data.dat", FileMode.Open)) {Person restored = (Person)formatter.Deserialize(stream);
}
(2)XML 序列化(跨平台可读)
- 优点:跨平台兼容,人类可读。
- 缺点:不支持私有字段,数据体积较大。
using System.Xml.Serialization;
XmlSerializer serializer = new XmlSerializer(typeof(Person));
using (TextWriter writer = new StreamWriter("data.xml")) {serializer.Serialize(writer, person);
}
using (TextReader reader = new StreamReader("data.xml")) {Person restored = (Person)serializer.Deserialize(reader);
}
(3)JSON 序列化(轻量通用)
- 优点:轻量级,广泛用于 Web API。
- 缺点:需第三方库(如 Newtonsoft.Json)。
using Newtonsoft.Json;
string json = JsonConvert.SerializeObject(person);
File.WriteAllText("data.json", json);
Person restored = JsonConvert.DeserializeObject<Person>(json);
(4)选型建议
| 场景 | 推荐方式 | 工具类/库 |
|---|
| 高性能 .NET 通信 | 二进制序列化 | BinaryFormatter |
| 跨平台/Web API | JSON 序列化 | Newtonsoft.Json 或 System.Text.Json |
| 配置文件/可读性需求 | XML 序列化 | XmlSerializer |
| 安全敏感场景 | JSON + 加密验证 | System.Text.Json + JWT |
(5)安全风险
BinaryFormatter 易受反序列化攻击(如注入恶意代码),.NET 5+ 已标记为过时。- 替代方案:优先使用
JsonSerializer(System.Text.Json)或 XmlSerializer。
3、Newtonsoft.Json
(1)安装依赖包
Install-Package Newtonsoft.Json
(2)基础操作
string json = JsonConvert.SerializeObject(obj, Formatting.Indented);
var obj = JsonConvert.DeserializeObject<T>(json);
File.WriteAllText("data.json", JsonConvert.SerializeObject(data, Formatting.Indented));
string json = File.ReadAllText("data.json");
var data = JsonConvert.DeserializeObject<Model>(json);
(3)空值忽略处理
public class User
{[JsonProperty("id")] public int UserId { get; set; }public string Name { get; set; }[JsonIgnore] public string Password { get; set; }[JsonProperty(NullValueHandling = NullValueHandling.Ignore)] public string Email { get; set; }
}
var user = new User { UserId = 1, Name = "Alice", Email = null };
var settings = new JsonSerializerSettings
{NullValueHandling = NullValueHandling.Ignore, Formatting = Formatting.Indented
};
JObject jo = JObject.FromObject(user, JsonSerializer.Create(settings));
jo.Remove("Password");
string json = jo.ToString();
(4)处理循环引用
public class Department
{public string Name { get; set; }public List<Employee> Employees { get; set; }
}public class Employee
{public string Name { get; set; }public Department Department { get; set; }
}
var settings = new JsonSerializerSettings
{PreserveReferencesHandling = PreserveReferencesHandling.Objects, ReferenceLoopHandling = ReferenceLoopHandling.Serialize
};var dept = new Department { Name = "HR" };
var emp = new Employee { Name = "Bob", Department = dept };
dept.Employees = new List<Employee> { emp };string json = JsonConvert.SerializeObject(dept, settings);
(5)自定义转换器
public class UnixDateTimeConverter : JsonConverter
{public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer){var date = (DateTime)value;writer.WriteValue((date.ToUniversalTime() - new DateTime(1970, 1, 1)).TotalSeconds);}public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer){return DateTime.UnixEpoch.AddSeconds((long)reader.Value);}public override bool CanConvert(Type objectType) => objectType == typeof(DateTime);
}
public class Event
{[JsonConverter(typeof(UnixDateTimeConverter))]public DateTime EventTime { get; set; }
}
var eventObj = new Event { EventTime = DateTime.Now };
string json = JsonConvert.SerializeObject(eventObj);
(6)日期格式与枚举处理
var settings = new JsonSerializerSettings
{DateFormatString = "yyyy-MM-ddTHH:mm:ssZ", Converters = { new StringEnumConverter() }
};public class Order
{public DateTime CreateTime { get; set; }public OrderStatus Status { get; set; }
}public enum OrderStatus { Pending, Shipped }var order = new Order { CreateTime = DateTime.Now, Status = OrderStatus.Pending };
string json = JsonConvert.SerializeObject(order, settings);
(7)流式处理超大JSON
using (var streamReader = new StreamReader("large-file.json"))
using (var jsonReader = new JsonTextReader(streamReader))
{while (jsonReader.Read()){if (jsonReader.TokenType == JsonToken.StartObject){var obj = JObject.Load(jsonReader);Console.WriteLine(obj["id"]); }}
}
(8)最佳实践
- 复用
JsonSerializerSettings实例 - 敏感字段用
[JsonIgnore]代替手动移除 - 优先用
JsonConvert 静态方法简化调用 - 完整配置模板
var settings = new JsonSerializerSettings
{Formatting = Formatting.Indented,ContractResolver = new CamelCasePropertyNamesContractResolver(), NullValueHandling = NullValueHandling.Ignore,DefaultValueHandling = DefaultValueHandling.Ignore,DateParseHandling = DateParseHandling.DateTimeOffset,Converters = { new StringEnumConverter(),new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AdjustToUniversal }},ReferenceLoopHandling = ReferenceLoopHandling.Ignore,PreserveReferencesHandling = PreserveReferencesHandling.None
};
4、Newtonsoft集成到ASP.NETCore
(1)安装依赖包
Install-Package Newtonsoft.Json
Install-Package Microsoft.AspNetCore.Mvc.NewtonsoftJson
(2)全局配置复用
- 在
Startup.ConfigureServices 全局配置 JsonSerializerSettings - 所有控制器自动复用同一配置,避免重复创建开销
- 统一处理日期、空值、枚举等规则
public void ConfigureServices(IServiceCollection services)
{var jsonSettings = new JsonSerializerSettings {Formatting = Formatting.Indented,NullValueHandling = NullValueHandling.Ignore,ContractResolver = new CamelCasePropertyNamesContractResolver(),DateFormatString = "yyyy-MM-ddTHH:mm:ssZ",Converters = { new StringEnumConverter() }};services.AddControllers().AddNewtonsoftJson(options => {options.SerializerSettings = jsonSettings; });
}
(3)通过依赖注入复用
- 若需在非控制器代码(如服务层)中复用,可通过 DI 注入配置:
services.AddSingleton(jsonSettings);
public class DataService
{private readonly JsonSerializerSettings _settings;public DataService(JsonSerializerSettings settings) => _settings = settings;public string SerializeData(object data) => JsonConvert.SerializeObject(data, _settings);
}