Newtonsoft.json: Serializar e desserializar do Dicionário<string list="">&gt; não funciona com [JsonProperty(ItemTypeNameHandling = TypeNameHandling.Auto, TypeNameHandling = TypeNameHandling.Auto)]</string>

Criado em 17 dez. 2014  ·  3Comentários  ·  Fonte: JamesNK/Newtonsoft.Json

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.

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:

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; }
}

Todos 3 comentários

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; }
}
Esta página foi útil?
0 / 5 - 0 avaliações