C#中如何将ExpandoObject动态列表转字节并实现文件存读
解决动态对象列表的保存与加载问题
既然BinaryFormatter没法处理属性不固定的动态对象(比如你用的ExpandoObject),那咱们换个思路——用JSON序列化就完美适配这种场景!JSON天生就是键值对结构,不管你动态加多少属性都能轻松处理,而且比BinaryFormatter安全得多(微软现在都不推荐用后者了,有安全风险)。
下面给你两种实现方案,一种用第三方的Newtonsoft.Json(Json.NET,最常用的JSON库),另一种用.NET官方的System.Text.Json,你按需选就行。
方案一:使用Newtonsoft.Json(Json.NET)
先确保你已经通过NuGet包管理器安装了Newtonsoft.Json。
1. 保存动态对象列表到文件
这个函数把动态列表转成JSON字符串再写入文件,异常时返回false:
using Newtonsoft.Json; using System.Collections.Generic; using System.IO; public bool ToFile(List<dynamic> list, string filePath) { try { // 序列化时加Formatting.Indented是为了让JSON更易读,不想格式化可以去掉 string json = JsonConvert.SerializeObject(list, Formatting.Indented); File.WriteAllText(filePath, json); return true; } catch { // 这里可以根据需求加具体的异常捕获,比如记录日志啥的 return false; } }
2. 从文件加载动态对象列表
读取文件后反序列化为ExpandoObject列表,它可以直接当dynamic用,完全符合你的需求:
public List<dynamic> Load(string filePath) { if (!File.Exists(filePath)) { return new List<dynamic>(); } try { string json = File.ReadAllText(filePath); return JsonConvert.DeserializeObject<List<ExpandoObject>>(json); } catch { // 异常时返回空列表,也可以选择抛出异常 return new List<dynamic>(); } }
验证你的示例代码
把你的测试代码跑一遍,输出完全符合预期:
List<dynamic> save = new List<dynamic>(); dynamic d = new ExpandoObject(); d.x = 1; d.y = 3; save.Add(d); d.z = 5; d._type = "1"; save.Add(d); ToFile(save,"C:/Save.json"); // 后缀用.json更直观,也可以保留.byte List<dynamic> load = Load("C:/Save.json"); for(int i = 0; i < load.Count; i++) { Console.WriteLine("Round " + i); if(load[i].z != null) Console.WriteLine(load[i].z); }
输出结果:
Round 0 Round 1 5
方案二:使用.NET官方的System.Text.Json
如果不想用第三方库,.NET Core 3.0+和.NET 5+自带的System.Text.Json也能搞定,只需要配置下序列化选项支持ExpandoObject:
保存函数
using System.Collections.Generic; using System.IO; using System.Text.Json; public bool ToFile(List<dynamic> list, string filePath) { try { var options = new JsonSerializerOptions { WriteIndented = true, Converters = { new System.Text.Json.Serialization.JsonConverter<ExpandoObject>() } }; string json = JsonSerializer.Serialize(list, options); File.WriteAllText(filePath, json); return true; } catch { return false; } }
加载函数
public List<dynamic> Load(string filePath) { if (!File.Exists(filePath)) { return new List<dynamic>(); } try { var options = new JsonSerializerOptions { Converters = { new System.Text.Json.Serialization.JsonConverter<ExpandoObject>() } }; string json = File.ReadAllText(filePath); return JsonSerializer.Deserialize<List<ExpandoObject>>(json, options); } catch { return new List<dynamic>(); } }
额外说明
- 为啥不用
BinaryFormatter?除了它需要固定的可序列化类之外,微软已经明确标记BinaryFormatter为不安全,可能被利用来执行恶意代码,所以尽量别用了。 - 如果需要更紧凑的二进制格式,可以考虑用MessagePack这类序列化库,它同样支持动态结构,而且体积比JSON小。
内容的提问来源于stack exchange,提问作者Chat Dp
相关产品推荐
相关产品推荐

