I have an object, which contains several dictionary types Which gets serialized to a Json
public class Foo
{
public Dictionary<string, bool> SomeDict {get;set;}
public ConcurrentDictionary<string, complextype> SomeconcurrentDict {Get;set;}
}
Now as this answer explains I require a converter to do so. Using that answer as a sample I created the following, so that it could apply to both the dictionary and the concurrentdictionary.
public class JsonDictionaryConverter<k, v> : CustomCreationConverter<IDictionary<k, v>>
{
public override IDictionary<k, v> Create(Type objectType)
=> Activator.CreateInstance(objectType) as IDictionary<k, v>;
// in addition to handling IDictionary<string, object>, we want to handle the deserialization of dict value, which is of type object
public override bool CanConvert(Type objectType) => objectType == typeof(object) || base.CanConvert(objectType);
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.StartObject || reader.TokenType == JsonToken.Null)
return base.ReadJson(reader, objectType, existingValue, serializer);
// if the next token is not an object
// then fall back on standard deserializer (strings, numbers etc.)
return serializer.Deserialize(reader);
}
}
However due to the as
casting to IDictionary<k,v>
failing, and resulting in a NULL, instead of an IDictionary, I run into a null reference exception down the line.
The activator create object is however a ConcurrentDictionary, with matching K and V values, which makes me assume that casting it as IDictionary<k,v>
should be possible.
So how can the activator instantiated object be cast to a IDictionary<k,v>
?
With the attribute applied, the class looks as following.
public class Foo
{
[JsonConverter(typeof(JsonDictionaryConverter<string,bool>))]
public Dictionary<string, bool> SomeDict {get;set;}
[JsonConverter(typeof(JsonDictionaryConverter<string,complextype>))]
public ConcurrentDictionary<string, complextype> SomeconcurrentDict {Get;set;}
}
A simplified test scenario on .netfiddler seems to run the code just fine, resulting in nicely created objects.
On my local machine, using a nearly identical object however, this results in the nullrefference exception due to the cast resulting in a NULL
public class Settings
{
[JsonConverter(typeof(JsonDictionaryConverter<string,string>))]
public ConcurrentDictionary<string, string> Prefix { get; set; }
[JsonConverter(typeof(JsonDictionaryConverter<string,bool>))]
public ConcurrentDictionary<string, bool> AllowMentions { get; set; }
public BotSettings()
{
Prefix = new ConcurrentDictionary<string, string>();
AllowMentions = new ConcurrentDictionary<string, bool>();
}
public Settings LoadSettings()
{
Settings settings = null;
// Temporary hardcoded json, for debug purposes
if (File.Exists(file))
settings = Serializer.DeserializeJson<BotSettings>("{\"Prefix\":{\"164427220197179403\":\".\",\"342638529622310925\":\".\"},\"AllowMentions\":{\"164427220197179403\":true,\"342638529622310925\":true}}");//string.Join(" ", ReadLines(file)));
return settings;
}
}