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。

有人有解决这个问题的经验吗?任何帮助都非常感谢!

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

在以下线程中解决了类似的问题:如何使用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);

将工作,因此反序列化也工作。

我不能说为什么会这样