Skip to main content
 首页 » 编程设计

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

2024年02月13日29pander-it

我正在尝试序列化(然后反序列化)一个 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); 

无法解析字典类型,因为它找不到 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; 
} 

但这对我来说似乎非常脆弱,因为它只解决了这个特定程序集的问题,我必须为我在某处需要的每个程序集添加另一个案例。

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

请您参考如下方法:

以下线程中解决了类似的问题:How can I deserialize with TypeNameHandling.Objects in Json.NET Silverlight?

问题似乎是 Json 无法加载具有部分名称的程序集。您可以使用 TypeNameAssemblyFormat = FormatterAssemblyStyle.Full 来解决这个问题。