Json.. NET无法序列化集合字典
本文关键字:集合 字典 序列化 NET Json | 更新日期: 2023-09-27 18:03:12
我正在尝试序列化(稍后反序列化)一个Dictionary<string, ISet<string>>
。不幸的是,Json。NET (v6.0.3通过NuGet)无法做到这一点。我要做的是
var value = new Dictionary<string, ISet<string>>
{
{"foo", new HashSet<string>{"bar"}}
};
var settings = new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.Objects,
TypeNameAssemblyFormat = FormatterAssemblyStyle.Simple
};
var json = JsonConvert.SerializeObject(value, settings);
变量json
保存字符串
{"$type":"System.Collections.Generic.Dictionary`2[[System.String, mscorlib],[System.Collections.Generic.ISet`1[[System.String, mscorlib]], System]], mscorlib","foo":["bar"]}
现在我想用
反序列化字符串JsonConvert.DeserializeObject<IDictionary<string, ISet<string>>>(json, settings);
无法解析Dictionary类型,因为它找不到ISet
所属的System
集合。当我执行以下命令
JsonConvert.DeserializeObject<IDictionary<string, ISet<string>>>(json);
一切正常。因此,TypeNameHandling
设置(更改/省略格式不会改变任何东西)实际上破坏了反序列化。
我发现,如果我不设置TypeNameHandling
设置,序列化的$type
属性就会被忽略。也就是说,在反序列化时,类型信息仅从解析它们的目标类型中获取。这工作。
设置TypeNameHandling
时,类型解析通过Json中的反射发生。. NET程序集,该程序集不依赖于System
程序集,因此无法解析ISet
接口。我可以通过在AppDomain.CurrentDomain.AssemblyResolve
上注册并解析像这样的汇编来解决这个问题
if (args.Name == "System")
{
return typeof (ISet<>).Assembly;
}
但是这对我来说似乎很脆弱,因为它只解决了这一个特定集合的问题,我必须为我需要的每个集合添加另一个case。
有人有解决这个问题的经验吗?任何帮助都非常感谢!
在以下线程中解决了类似的问题:如何使用TypeNameHandling进行反序列化?Json中的对象。净Silverlight吗?
问题似乎是Json无法加载部分名称的程序集。您可以通过使用TypeNameAssemblyFormat = FormatterAssemblyStyle.Full
来解决这个问题。
如果您检查NewtonSoft的源代码。DefaultSerializationBinder中的Json。GetTypeNameFromTypeNameKey约。行83年. .它试图获取类型
System.Collections.Generic。字典2[[System.String, mscorlib],[System.Collections.Generic.ISet
1[[系统。字符串,mscorlib]], System]]
from assembly
mscorlib.dll
Type type = assembly.GetType(typeName);
返回null。这是与FormatterAssemblyStyle.Simple.
如果你使用FormatterAssemblyStyle。Full则相同的类型为:
System.Collections.Generic。字典2[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.Collections.Generic.ISet
1[[系统。String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]
然后:
Type type = assembly.GetType(typeName);
将工作,因此反序列化也工作。
我不能说为什么会这样