7

I am using Json.NET to deserialized an object which included a nested Dictionary. Here is a sample of what i am trying to do

public interface IInterface
{
    String Name { get; set; }
}

public class AClass : IInterface
{
    public string Name { get; set; }
}

public class Container
{
    public Dictionary<IInterface, string> Map { get; set; }
    public Container()
    {
        Map = new Dictionary<IInterface, string>();
    }
}


public static void Main(string[] args)
    {
        var container = new Container();
        container.Map.Add(new AClass()
        {
            Name = "Hello World"
        }, "Hello Again");
        var settings = new JsonSerializerSettings
        {
            TypeNameHandling = TypeNameHandling.Objects,
            PreserveReferencesHandling = PreserveReferencesHandling.All,

        };


        string jsonString = JsonConvert.SerializeObject(container, Formatting.Indented, settings);
        var newContainer = JsonConvert.DeserializeObject<Container>(jsonString);
    }

I received exception message: Could not convert string 'ConsoleApplication1.AClass' to dictionary key type 'ConsoleApplication1.IInterface'. Create a TypeConverter to convert from the string to the key type object. Please accept my apology however I cant find a way to de-serialize interface in Dictionary key.

Thank you very much in advance

duongthaiha
  • 810
  • 6
  • 16

1 Answers1

12

The issue is that JSON dictionaries (objects) only support string keys, so Json.Net converts your complex key type to a Json string (calling ToString()) which can't then be deserialized into the complex type again. Instead, you can serialize your dictionary as a collection of key-value pairs by applying the JsonArray attribute.

See this question for details.

Community
  • 1
  • 1
ChaseMedallion
  • 20,111
  • 13
  • 84
  • 146
  • Thank you very much. Previous question suggest JsonArrayAttribute however it is only available for class but for as property. Is there anyway to mark a property with an collection or dictionary attribute please. – duongthaiha Jan 28 '14 at 10:53
  • 2
    @duongthaiha instead of making your property of type dictionary, can you create a derived class of dictionary with the attribute ad use that? – ChaseMedallion Jan 28 '14 at 16:14
  • 2
    Applying the `JsonArray` attribute requires that you subclass `Dictionary`. One alternative is to convert the dictionary to a `List>` by calling `ToList()` on the dictionary, and serializing the list instead. Then, when deserializing, convert it back to a dictionary using `ToDictionary(x => x.Key, x => x.Value)`. – Nate Cook Mar 04 '18 at 21:04