3

I have a hashtable whose keys are of type integer, however when deserializing using json.net the keys come back as strings, is there a way to keep the key type on hashtable using json.net serialization/deserialization? This hashtable is a property of the type 'MyType'

var settings = new JsonSerializerSettings();
settings.TypeNameHandling = TypeNameHandling.Objects;
string json = JsonConvert.SerializeObject(o, Formatting.Indented, settings);

 mo = JsonConvert.DeserializeObject<MyType>(json, new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Objects });

public Hashtable jsonViews
{
    get { return mViews; }
    set { mViews = value; }
}
Rafael
  • 1,099
  • 5
  • 23
  • 47
  • How are you deserializing the hashtable? Can you show the code please? – toadflakz Jan 14 '15 at 09:47
  • Can you post the MyType class as well please? At least the public properties... – toadflakz Jan 14 '15 at 09:55
  • The code is incomplete. Where is the definition of MyType? Please post the Json string produced, although I suspect the keys *are* serialized as strings, ie enclosed in `"`. – Panagiotis Kanavos Jan 14 '15 at 09:55
  • that's the property were the hashtable is accessed – Rafael Jan 14 '15 at 09:59
  • 2
    *Json* doesn't provide any schema so it's not good at preserving types. A key of `1` is just as valid as `"1"`. Unless you specify the type you want when deserializing, Json.NET (or any other library) will pick the most appropriate type - int for `1`, string for `"1"`. A HashTable's key is an Object, ie unspecified. If you want a specific key you should use a class like Dictionary<> or [MultiValueDictionary<>](http://blogs.msdn.com/b/dotnet/archive/2014/08/05/multidictionary-becomes-multivaluedictionary.aspx) – Panagiotis Kanavos Jan 14 '15 at 10:03

2 Answers2

10

The problem is that the System.Collections.Hashtable isn't strongly typed - it will hold any type of object, and JSON.NET is most likely serialising the string representation of your hashtable contents.

Before you spend too much time massaging the JSON.NET serializer/deserializer to compensate for this, you might want to consider switching your Hashtable out for a Dictionary<TKey, TValue>. It's almost identical in terms of performance, but gives you the advantage and safety of a strongly-typed collection.

A strongly-typed collection will resolve your Json.NET deserialization issues, as Json.NET can infer the type from the dictionary.

The use of Dictionary<TKey,TValue> over Hashtable is discussed here.

Community
  • 1
  • 1
olitee
  • 1,683
  • 10
  • 12
0

Here's a generic static extension method that I wrote to help me with this problem. I basically wanted this code to never blow up even if the data is somehow corrupted.

    public static T Read<T>(this Hashtable hash, string key)
    {
        if (!hash.ContainsKey(key))
            return default;
        if (hash[key] is T)
            return (T)hash[key];
        if (hash[key] is JToken token)
            return token.ToObject<T>();

        try
        {
            return (T)Convert.ChangeType(hash[key], typeof(T));
        }
        catch (InvalidCastException)
        {
            Debug.LogWarning($"{key} had the wrong type of {hash[key].GetType()}");
            return default;
        }
    }
Bryan Legend
  • 6,790
  • 1
  • 59
  • 60