我正在尝试序列化(以及稍后反序列化)Dictionary<string, ISet<string>>
。不幸的是,Json.NET(通过NuGet的v6.0.3)无法做到这一点。我的工作是
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类型,因为它无法找到System
所属的ISet
程序集。当我改为做以下
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;
}
但这对我来说似乎非常脆弱,因为它解决了这个特定程序集的问题,我必须为我需要的每个程序集添加另一个案例。
有没有人有如何解决这个问题的经验?非常感谢任何帮助!
答案 0 :(得分:3)
以下主题解决了类似的问题:How can I deserialize with TypeNameHandling.Objects in Json.NET Silverlight?
问题似乎是Json无法使用部分名称加载程序集。您可以使用TypeNameAssemblyFormat = FormatterAssemblyStyle.Full
来解决此问题。
答案 1 :(得分:1)
如果在DefaultSerializationBinder.GetTypeNameFromTypeNameKey中检查NewtonSoft.Json的源代码。第83行。它试图获取类型
System.Collections.Generic.Dictionary 2[[System.String, mscorlib],[System.Collections.Generic.ISet
1 [[System.String,mscorlib]],System]]
来自议会
mscorlib.dll中
Type type = assembly.GetType(typeName);
返回null。这与FormatterAssemblyStyle.Simple。
有关如果使用FormatterAssemblyStyle.Full,那么相同的类型将是:
System.Collections.Generic.Dictionary 2[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.Collections.Generic.ISet
1 [[System.String,mscorlib,Version = 4.0.0.0,Culture = neutral,PublicKeyToken = b77a5c561934e089]],System,Version = 4.0.0.0,Culture =中性,PublicKeyToken = b77a5c561934e089]]
然后:
Type type = assembly.GetType(typeName);
可以工作,因此反序列化也可以。
我不能说为什么会这样。