C#从文件反序列化对象 C#如何从文件中恢复对象实例

1次阅读

必须为类添加[serializable]标记才能用binaryformatter反序列化,但.net core 5+默认禁用该不安全方式;推荐使用system.text.json流式反序列化json文件,注意处理bom、换行符、类型匹配等问题。

C#从文件反序列化对象 C#如何从文件中恢复对象实例

反序列化前必须确认类型是否标记了 [Serializable]

如果类没加 [Serializable] 特性,BinaryFormatter 会直接抛出 SerializationException。即使类里所有字段都是可序列化的,缺这个标记也不行。

注意:.NET Core 5+ 和 .NET 6+ 默认禁用 BinaryFormatter,因为它有严重安全风险——反序列化任意二进制数据可能触发远程代码执行。除非你完全控制文件来源且运行在可信环境,否则别用它。

  • 替代方案优先选 System.Text.Json(推荐)或 Newtonsoft.Json
  • 若必须用二进制格式(如老系统兼容),改用 System.Runtime.Serialization.Formatters.Binary.BinaryFormatter 前,得在项目文件中显式启用:<enableunsafebinaryformatterserialization>true</enableunsafebinaryformatterserialization>
  • 标记类时,私有字段默认会被序列化;不想保存的字段加 [NonSerialized]

System.Text.Json 从 JSON 文件读取对象最安全

这是目前 C# 官方主推的方式,无需额外 NuGet 包(.NET Core 3.0+ 内置),默认忽略不可访问成员,不执行构造函数,天然防反序列化攻击。

示例代码片段:

var json = File.ReadAllText("data.json"); var obj = JsonSerializer.Deserialize<MyClass>(json);
  • 确保 MyClass 有公共 getter/setter 的属性,或配置 JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase 来匹配小驼峰命名
  • 如果文件含日期字符串,注意默认只支持 ISO 8601 格式(如 "2023-10-05T08:30:00"),非标准格式需自定义 JsonConverter<datetime></datetime>
  • 遇到 JsonException,大概率是 JSON 格式错误或字段类型不匹配,可用 JsonDocument.Parse(json) 先验证结构

FileStream + JsonSerializer 避免大文件内存爆涨

直接读整个文件到字符串再反序列化,对几百 MB 的 JSON 文件很容易 OOM。应流式处理。

正确做法:

using var stream = File.OpenRead("big-data.json"); var obj = await JsonSerializer.DeserializeAsync<MyClass>(stream);
  • 同步版本用 Deserialize<t>(Stream)</t>异步版本用 DeserializeAsync<t>(Stream)</t>
  • 不要用 File.ReadAllBytes() 再转 MemoryStream —— 这和读字符串一样占双倍内存
  • 如果目标类型是集合(如 List<item></item>),且文件是数组格式,可直接反序列化;如果是包裹对象(如 {"items":[...]}),得先定义对应包装类

反序列化失败时,别只看异常消息

JsonExceptionMessage 通常只说“invalid Token”,但真正问题往往藏在 LineNumberBytePositionInLine 属性里。

  • 捕获异常后打印这两个值,能快速定位 JSON 中哪一行哪个字符出错
  • 常见隐形坑:BOM 头(UTF-8 with BOM)、windows 换行符混入字符串字段、浮点数用了本地化小数点(如 "3,14" 而非 "3.14"
  • 调试阶段可在反序列化前用 JsonSerializer.Serialize(obj) 把对象打出来,对比原始文件,看差异在哪

类型不匹配比语法错误更难察觉——比如 JSON 里是字符串 "123",而 C# 字段是 int,默认会失败;此时可加 JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter()) 或自定义 converter 处理。

text=ZqhQzanResources