I'm trying to serialize (and later on deserialize) a Dictionary<string, ISet<string>>
. Unfortunately, Json.NET (v6.0.3 via NuGet) fails to do this. What I do is
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);
The variable json
then holds the string
{"$type":"System.Collections.Generic.Dictionary`2[[System.String, mscorlib],[System.Collections.Generic.ISet`1[[System.String, mscorlib]], System]], mscorlib","foo":["bar"]}
Now I want to deserialize the string with
JsonConvert.DeserializeObject<IDictionary<string, ISet<string>>>(json, settings);
which fails in resolving the Dictionary type, because it cannot find the System
assembly that ISet
belongs to. When I instead do the following
JsonConvert.DeserializeObject<IDictionary<string, ISet<string>>>(json);
everything works just fine. So it appears that the TypeNameHandling
setting (changing/omitting the format does not change anything) actually breaks deserialization.
I found that, if I don't set the TypeNameHandling
settings, the serialized $type
properties are simply ignored. I.e., when deserializing, the type information is taken solely from the target type where they are resolved. This works.
When setting the TypeNameHandling
, type resolution happens via reflection within the Json.NET assembly, which does not have a dependency on the System
assembly and therefore fails to resolve the ISet
interface. I can fix this by registering on AppDomain.CurrentDomain.AssemblyResolve
and resolving the assembly like so
if (args.Name == "System")
{
return typeof (ISet<>).Assembly;
}
but this seems very fragile to me, as it solves the problem for only this one specific assembly and I have to add another case for every assembly I need somewhere.
Does anyone have experience on how to solve this? Any help is greatly appreciated!