ASP.NET中JSON.NET序列化反序列化自定义类型值Hashtable类型丢失问题
问题根因
Hashtable是非泛型集合,内部存储的元素默认类型为object,JSON.NET默认序列化配置不会写入自定义引用类型的类型元数据,反序列化时无法识别元素原本的User类型,会默认解析为JObject对象,导致类型丢失无法直接强转。
可用解决方案
方案1:序列化时开启类型元数据写入(适配必须用Hashtable的场景)
序列化和反序列化时同步配置
TypeNameHandling.Auto,JSON.NET会在需要类型识别的对象节点上追加类型信息,反序列化时就能自动还原为原始User类型。注意:跨服务POST传输时建议同步将
TypeNameAssemblyFormatHandling设为Simple,避免序列化结果带完整程序集强名称信息,导致接收端类型匹配失败,只要收发两端User类的命名空间、类名、结构一致即可正常解析。
示例代码:// 初始化序列化配置 JsonSerializerSettings settings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Auto, TypeNameAssemblyFormatHandling = TypeNameAssemblyFormatHandling.Simple }; // 原有序列化逻辑 Hashtable ht = new Hashtable(); User u = new User(); u.name = "username"; u.last = "userlastname"; u.age = 30; ht.Add("user1", u); ht.Add("user2", u); ht.Add("user3", u); ht.Add("user4", u); string value = JsonConvert.SerializeObject(ht, settings); // 反序列化时传入相同配置即可 Hashtable result = JsonConvert.DeserializeObject<Hashtable>(value, settings); // 取出的值可直接强转为User类型 User user1 = (User)result["user1"];方案2:替换为泛型Dictionary(推荐最佳实践)
Hashtable是C#泛型特性推出前的遗留非泛型类型,当键值对的值类型固定为User时,优先使用泛型Dictionary<string, User>替代,泛型集合本身携带明确的类型信息,不需要额外配置类型元数据即可完成正确的序列化、反序列化,性能和类型安全性都更高。
示例代码:Dictionary<string, User> dict = new Dictionary<string, User>(); User u = new User(); u.name = "username"; u.last = "userlastname"; u.age = 30; dict.Add("user1", u); dict.Add("user2", u); dict.Add("user3", u); dict.Add("user4", u); // 序列化无需额外配置 string value = JsonConvert.SerializeObject(dict); // 反序列化直接指定泛型类型,取出的值天然是User类型,无需强转 Dictionary<string, User> result = JsonConvert.DeserializeObject<Dictionary<string, User>>(value); User user1 = result["user1"];方案3:反序列化后手动转换类型(适配无法修改序列化逻辑的场景)
如果序列化端无法修改配置(比如接收第三方/前端传来的JSON数据),可以在反序列化得到Hashtable后,将内部存储的
JObject对象手动转换为User类型。
示例代码:Hashtable result = JsonConvert.DeserializeObject<Hashtable>(value); foreach (DictionaryEntry entry in result) { if (entry.Value is JObject jObj) { User user = jObj.ToObject<User>(); // 对转换后的User对象做后续处理 } }
内容的提问来源于stack exchange,提问作者Labib Mezghanni
相关产品推荐
相关产品推荐

