Search code examples
c#asp.netjsondeserializationjson-deserialization

Exception when deserializing json


I have 2 methods

public static string SerializeObject<T>(T value)
{
    if (value == null)
    {
        return null;
    }

    var dictionaryObject = new Dictionary<string, object> { { typeof(T).Name, value } };

    var jsonString = JsonConvert.SerializeObject(dictionaryObject);

    return jsonString;
}

and

public static T DeserializeObject<T>(string jsonString)
{
    var objectValue = JsonConvert.DeserializeObject<Dictionary<string, object>>(jsonString);
    return JsonConvert.DeserializeObject<T>(objectValue.Values.First().ToString());
}

When I deserialize a json string with type

ConcurrentDictionary<KeyValuePair<long, long>, IList<string>>

I have an exception:

Could not convert string '[1, 1]' to dictionary key type 'System.Collections.Generic.KeyValuePair`2[System.Int64,System.Int64]'. Create a TypeConverter to convert from the string to the key type object. Path '[1, 1]', line 2, position 12.

So Can someone show me the right code for it to work?

Here is my code:

var test = new ConcurrentDictionary<KeyValuePair<long, long>, IList<string>>();
test.TryAdd(new KeyValuePair<long, long>(1, 1), new List<string> { "Test" });

var se = SerializeObject(test);

var de = DeserializeObject<ConcurrentDictionary<KeyValuePair<long, long>, IList<string>>>(se);

Solution

  • I'm not sure if this is the best solution, but, please, try this:

    1) create ContractResolver as described in this topic.

    class DictionaryAsArrayResolver : DefaultContractResolver
            {
                protected override JsonContract CreateContract(Type objectType)
                {
                    if (objectType.GetInterfaces().Any(i => i == typeof(IDictionary) ||
                        (i.IsGenericType &&
                         i.GetGenericTypeDefinition() == typeof(IDictionary<,>))))
                    {
                        return base.CreateArrayContract(objectType);
                    }
    
                    return base.CreateContract(objectType);
                }
            }
    

    2) Change a bit your Serialize/Deserialize methods:

    public static string SerializeObject<T>(T value, JsonSerializerSettings settings)
            {
                if (value == null)
                {
                    return null;
                }
    
                var dictionaryObject = new Dictionary<string, object> { { typeof(T).Name, value } };
                var jsonString = JsonConvert.SerializeObject(dictionaryObject, settings);
    
                return jsonString;
            }
    
            public static T DeserializeObject<T>(string jsonString, JsonSerializerSettings settings)
            {
                var objectValue = JsonConvert.DeserializeObject<Dictionary<string, object>>(jsonString, settings);
                return JsonConvert.DeserializeObject<T>(objectValue.Values.First().ToString(), settings);
            }
    

    3) Check the test:

    [TestMethod]
            public void Test()
            {
                var test = new ConcurrentDictionary<KeyValuePair<long, long>, IList<string>>();
                test.TryAdd(new KeyValuePair<long, long>(1, 1), new List<string> { "Test" });
    
                JsonSerializerSettings settings = new JsonSerializerSettings();
                settings.ContractResolver = new DictionaryAsArrayResolver();
    
                var se = SerializeObject(test, settings);
    
                var de = DeserializeObject<ConcurrentDictionary<KeyValuePair<long, long>, IList<string>>>(se, settings);
            }
    

    I hope, it helps =)