Quando tento serializar e desserializar uma propriedade do tipo Dictionary<string, List<MyInterface>>
, Newtonsoft não adiciona a propriedade $type na IMyInterface mesmo se eu definir o atributo [JsonProperty(ItemTypeNameHandling = TypeNameHandling.Auto, TypeNameHandling = TypeNameHandling.Auto)]
Amostra :
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; }
}
Se eu definir as configurações globais TypeNameHandling = TypeNameHandling.Auto
ao serializar e desserializar, funciona.
Eu encontrei este problema que é realmente semelhante ao meu http://json.codeplex.com/workitem/18046 e que deveria ser corrigido desde 2010, mas se eu executar o exemplo dele, ele também trava como eu.
ItemTypeNameHandling = TypeNameHandling.Auto em sua propriedade Rows se aplica ao conteúdo do dicionário (ou seja, List<>), não ao conteúdo da lista.
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);
}
Seu caso de teste não cobre meu caso de uso. Eu tenho várias implementações de IMyInterfaceType
que preciso colocar na minha lista. Aqui está um exemplo melhor:
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; }
}
Comentários muito úteis
Seu caso de teste não cobre meu caso de uso. Eu tenho várias implementações de
IMyInterfaceType
que preciso colocar na minha lista. Aqui está um exemplo melhor: