C#序列化对象到文件 C#如何将对象保存为二进制或JSON文件

来源:这里教程网 时间:2026-02-21 17:43:05 作者:

BinaryFormatter
保存二进制文件?别用了

从 .NET Core 3.0 开始,

BinaryFormatter
已被标记为过时(obsolete),且默认禁用——它存在严重反序列化安全风险,微软明确不推荐在任何新项目中使用。即使你强制启用,.NET 6+ 也会在运行时抛出
NotSupportedException

如果你真需要二进制序列化(比如老系统兼容、高性能本地缓存),可改用

System.Text.Json
的二进制编码变体(需搭配
JsonSerializerOptions
+
Utf8JsonWriter
写入
MemoryStream
),但更现实的选择是:直接用 JSON,或换用
MessagePack
这类安全、紧凑的二进制格式。

不要在生产环境写
new BinaryFormatter().Serialize(...)
若必须读取旧的
.bin
文件,用
BinaryFormatter
仅限于可信、隔离的脱机场景,并确保反序列化类型白名单严格控制
替代方案优先级:JSON(通用)→ MessagePack(紧凑+快)→ Protocol Buffers(跨语言)

System.Text.Json
序列化到 JSON 文件(推荐)

System.Text.Json
是 .NET 5+ 默认内置的高性能 JSON 库,无需安装 NuGet,支持异步、流式读写、自定义转换器,且默认忽略循环引用(不会崩溃)。

最简保存方式:

var options = new JsonSerializerOptions { WriteIndented = true };
File.WriteAllText("user.json", JsonSerializer.Serialize(user, options));

注意几个关键点:

WriteIndented = true
仅用于调试,生产环境建议关掉以减小体积
若对象含
DateTime
,默认序列化为 ISO 8601 字符串(如
"2024-05-20T14:30:00Z"
),无需额外配置
私有字段默认不序列化;要包含,加
[JsonPropertyName("xxx")]
或设置
IncludeFields = true
DefaultIgnoreCondition = JsonIgnoreCondition.Never
遇到
NotSupportedException
(如含
DBNull
IntPtr
或自定义不可序列化类型),说明该类型没实现
JsonConverter
,需手动注册转换器

Newtonsoft.Json
(Json.NET)保存时要注意什么

虽然

System.Text.Json
是官方推荐,但很多老项目仍依赖
Newtonsoft.Json
。它更灵活,但也更容易踩坑。

基础写法:

File.WriteAllText("user.json", JsonConvert.SerializeObject(user, Formatting.Indented));

常见陷阱:

默认会序列化所有 public 属性和字段,包括
get; set;
自动属性的 backing field(如果用了
[JsonIgnore]
就没事)
DateTime
默认按本地时区输出,易引发时区混淆;建议统一用
JsonConvert.SerializeObject(..., new JsonSerializerSettings { DateTimeZoneHandling = DateTimeZoneHandling.Utc })
若对象里有
JObject
JArray
,它们会被原样嵌入,但后续用
System.Text.Json
读取会失败——混用库时务必统一序列化格式
大对象(>85KB)可能触发 LOH(Large Object Heap)分配,频繁操作影响 GC 性能;此时应改用
JsonTextWriter
流式写入

异步保存和错误处理不能省

直接调用

File.WriteAllText
会阻塞线程,尤其在 UI 或 ASP.NET Core 请求线程中容易拖慢响应。真正可用的写法是异步 + 异常包裹:

try
{
    var json = JsonSerializer.Serialize(user, new JsonSerializerOptions { WriteIndented = false });
    await File.WriteAllTextAsync("user.json", json);
}
catch (UnauthorizedAccessException)
{
    // 检查目录是否有写权限,或文件是否被其他进程占用(如 Excel 正在打开该文件)
}
catch (IOException ex) when (ex.Message.Contains("The process cannot access the file"))
{
    // 文件被独占锁定,考虑加重试或提示用户关闭相关程序
}

另外,路径必须合法:

Directory.CreateDirectory(Path.GetDirectoryName("data/user.json"))
要提前执行,否则
File.WriteAllTextAsync
会直接抛
DirectoryNotFoundException

最后提醒:JSON 不适合存二进制数据(如图片、音频)。这类内容应 Base64 编码后作为字符串字段存入,但体积膨胀约 33%;更合理的方式是单独保存为文件,JSON 中只存路径或哈希值。

相关推荐

热文推荐