C# Json.NET无法序列化集合的字典

C# Json.NET无法序列化集合的字典,c#,serialization,dictionary,set,json.net,C#,Serialization,Dictionary,Set,Json.net,我正在尝试序列化(稍后反序列化)一个字典。不幸的是,Json.NET(通过NuGet的v6.0.3)未能做到这一点。我所做的是 var value = new Dictionary<string, ISet<string>> { {"foo", new HashSet<string>{"bar"}} }; var settings = new JsonSerializerSettings { TypeNa

我正在尝试序列化(稍后反序列化)一个
字典
。不幸的是,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);
现在我想用

JsonConvert.DeserializeObject<IDictionary<string, ISet<string>>>(json, settings);
一切正常。因此,
typenameholling
设置(更改/省略格式不会更改任何内容)实际上破坏了反序列化

我发现,如果不设置
typenameholling
设置,序列化的
$type
属性就会被忽略。即,在反序列化时,类型信息仅从解析它们的目标类型获取。这很有效

设置
TypeNameHandling
时,类型解析是通过Json.NET程序集中的反射进行的,该程序集不依赖于
系统
程序集,因此无法解析
ISet
接口。我可以通过注册AppDomain.CurrentDomain.AssemblyResolve来解决这个问题,然后像这样解析程序集

if (args.Name == "System")
{
     return typeof (ISet<>).Assembly;
}
if(args.Name==“系统”)
{
返回类型(ISet)。组件;
}
但这对我来说似乎非常脆弱,因为它只解决了这个特定组件的问题,我必须为我需要的每个组件添加另一个案例


有没有人有解决这个问题的经验?非常感谢您的帮助

在以下线程中解决了类似的问题:


问题似乎是Json无法加载具有部分名称的程序集。通过使用
TypeNameAssemblyStyle=FormatterAssemblyStyle.Full

可以解决此问题。以下线程解决了类似问题:


问题似乎是Json无法加载具有部分名称的程序集。如果您在DefaultSerializationBinder.GetTypeNameFromTypeNameKey的第83行中检查NewtonSoft.Json的源代码,则可以通过使用
TypeNameAssemblyFormat=FormatterAssemblyStyle.Full
来克服此问题。。它尝试获取类型

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]],系统,版本=4.0.0.0,区域性=中性,PublicKeyToken=b77a5c561934e089]]

然后:

Type type = assembly.GetType(typeName);
将起作用,因此反序列化也起作用


但是,我无法解释为什么会出现这种情况。

如果您检查DefaultSerializationBinder.GetTypeNameFromTypeNameKey第83行中NewtonSoft.Json的源代码。。它尝试获取类型

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]],系统,版本=4.0.0.0,区域性=中性,PublicKeyToken=b77a5c561934e089]]

然后:

Type type = assembly.GetType(typeName);
将起作用,因此反序列化也起作用


我说不出为什么会这样。

ISet驻留在System.dll中。您的示例在json.NET和.NET 4.5的同一版本中运行良好。有趣的是,我使用的是.NET 4.0,但我认为这不是问题所在。。。我会深入研究的。我在将设置传递到反序列化中时找到了错误的原因。我相应地更新了我的问题。虽然眼前的问题已经解决了,但我真的很感兴趣,为什么传递设置会导致此错误!ISet驻留在System.dll中。您的示例在json.NET和.NET 4.5的同一版本中运行良好。有趣的是,我使用的是.NET 4.0,但我认为这不是问题所在。。。我会深入研究的。我在将设置传递到反序列化中时找到了错误的原因。我相应地更新了我的问题。虽然眼前的问题已经解决了,但我真的很感兴趣,为什么传递设置会导致此错误!很抱歉我之前的评论,这确实解决了问题。虽然我不太明白为什么。。。谢谢很抱歉我之前的评论,这确实解决了问题。虽然我不太明白为什么。。。谢谢谢谢你的解释,帮了我很多忙+1美元。不过,我接受爱丁的回答,因为他早些时候提出了同样的解决方案。不过,非常感谢!谢谢你的解释,帮了我很多忙+1美元。不过,我接受爱丁的回答,因为他早些时候提出了同样的解决方案。不过,非常感谢!