Newtonsoft.json: Serialize and deserialize of Dictionary<string, List<IMyInterface>> doesn't work with [JsonProperty(ItemTypeNameHandling = TypeNameHandling.Auto, TypeNameHandling = TypeNameHandling.Auto)]

Created on 17 Dec 2014  路  3Comments  路  Source: JamesNK/Newtonsoft.Json

When I try to serialize and deserialize a property of type Dictionary<string, List<MyInterface>>, Newtonsoft doesn't add the $type property in the IMyInterface even if I set the attribute [JsonProperty(ItemTypeNameHandling = TypeNameHandling.Auto, TypeNameHandling = TypeNameHandling.Auto)]

Sample :

static void Main(string[] args)
{
    Data data = new Data();
    data.Rows.Add("key", new List<IMyInterface>() { new MyInterfaceImplementation() { SomeProperty = "property" } });
    string serialized = JsonConvert.SerializeObject(data);
    Data deserialized = JsonConvert.DeserializeObject<Data>(serialized);
}

public class Data
{
    public Data()
    {
        this.Rows = new Dictionary<string, List<IMyInterface>>();
    }

    [JsonProperty(ItemTypeNameHandling = TypeNameHandling.Auto, TypeNameHandling = TypeNameHandling.Auto)]
    public Dictionary<string, List<IMyInterface>> Rows { get; private set; }
}

public interface IMyInterface
{
    string SomeProperty { get; set; }
}

public class MyInterfaceImplementation : IMyInterface
{
    public string SomeProperty { get; set; }
}

If I set a the global settings TypeNameHandling = TypeNameHandling.Auto when serializing and deserializing, it works.

I found this issue that is really similar to mine http://json.codeplex.com/workitem/18046 and that is supposed to be fixed since 2010, but if I run his sample, it also crashes like me.

Most helpful comment

Your test case doesn't cover my use case. I have multiple implementations of IMyInterfaceType that I need to put in my list. Here's a better example :

static void Main(string[] args)
{
    DataType data = new DataType();
    List<IMyInterfaceType> myInterfaceType = new List<IMyInterfaceType>();
    myInterfaceType.Add(new MyInterfaceImplementationType() { SomeProperty = "property" });
    myInterfaceType.Add(new MySecondInterfaceImplementationType() { SomeProperty = "property2" });
    data.Rows.Add("key", myInterfaceType);

    string serialized = JsonConvert.SerializeObject(data, Formatting.Indented);

    DataType deserialized = JsonConvert.DeserializeObject<DataType>(serialized);
}


public class DataType
{
    public DataType()
    {
        Rows = new Dictionary<string, IEnumerable<IMyInterfaceType>>();
    }

    [JsonProperty(ItemTypeNameHandling = TypeNameHandling.Auto, TypeNameHandling = TypeNameHandling.Auto)]
    public Dictionary<string, IEnumerable<IMyInterfaceType>> Rows { get; private set; }
}


public interface IMyInterfaceType
{
    string SomeProperty { get; set; }
}

public class MyInterfaceImplementationType : IMyInterfaceType
{
    public string SomeProperty { get; set; }
}

public class MySecondInterfaceImplementationType : IMyInterfaceType
{
    public string SomeProperty { get; set; }
}

All 3 comments

ItemTypeNameHandling = TypeNameHandling.Auto on your Rows property applies to the contents of the dictionary (i.e. List<>), not the contents of the list.

public class DataType
{
    public DataType()
    {
        Rows = new Dictionary<string, IEnumerable<IMyInterfaceType>>();
    }

    [JsonProperty(ItemTypeNameHandling = TypeNameHandling.Auto, TypeNameHandling = TypeNameHandling.Auto)]
    public Dictionary<string, IEnumerable<IMyInterfaceType>> Rows { get; private set; }
}


public interface IMyInterfaceType
{
    string SomeProperty { get; set; }
}

public class MyInterfaceImplementationType : IMyInterfaceType
{
    public string SomeProperty { get; set; }
}


    [Test]
    public void GenericItemTypeCollection()
    {
        DataType data = new DataType();
        data.Rows.Add("key", new List<MyInterfaceImplementationType> { new MyInterfaceImplementationType() { SomeProperty = "property" } });
        string serialized = JsonConvert.SerializeObject(data, Formatting.Indented);

        DataType deserialized = JsonConvert.DeserializeObject<DataType>(serialized);

        Assert.AreEqual("property", deserialized.Rows["key"].First().SomeProperty);
    }

Your test case doesn't cover my use case. I have multiple implementations of IMyInterfaceType that I need to put in my list. Here's a better example :

static void Main(string[] args)
{
    DataType data = new DataType();
    List<IMyInterfaceType> myInterfaceType = new List<IMyInterfaceType>();
    myInterfaceType.Add(new MyInterfaceImplementationType() { SomeProperty = "property" });
    myInterfaceType.Add(new MySecondInterfaceImplementationType() { SomeProperty = "property2" });
    data.Rows.Add("key", myInterfaceType);

    string serialized = JsonConvert.SerializeObject(data, Formatting.Indented);

    DataType deserialized = JsonConvert.DeserializeObject<DataType>(serialized);
}


public class DataType
{
    public DataType()
    {
        Rows = new Dictionary<string, IEnumerable<IMyInterfaceType>>();
    }

    [JsonProperty(ItemTypeNameHandling = TypeNameHandling.Auto, TypeNameHandling = TypeNameHandling.Auto)]
    public Dictionary<string, IEnumerable<IMyInterfaceType>> Rows { get; private set; }
}


public interface IMyInterfaceType
{
    string SomeProperty { get; set; }
}

public class MyInterfaceImplementationType : IMyInterfaceType
{
    public string SomeProperty { get; set; }
}

public class MySecondInterfaceImplementationType : IMyInterfaceType
{
    public string SomeProperty { get; set; }
}
Was this page helpful?
0 / 5 - 0 ratings