2010-09-17 7 views
34

J'essaie de sérialiser/désérialiser un Dictionary<string, object> qui semble fonctionner correctement si l'objet est de type simple mais ne fonctionne pas lorsque l'objet est plus complexe.Sérialisation/désérialisation Dictionnaire d'objets avec JSON.NET

J'ai cette classe:

public class UrlStatus 
{ 
public int Status { get; set; } 
public string Url { get; set; } 
} 

Dans mon dictionnaire ajouter une List<UrlStatus> avec une clé de « Rediriger Chain » et quelques cordes simples avec les touches « Status », « URL », « URL parent » . La chaîne Je reviens de JSON.Net ressemble à ceci:

{"$type":"System.Collections.Generic.Dictionary`2[[System.String, mscorlib],[System.Object, mscorlib]], mscorlib","Status":"OK","Url":"http://www.ehow.com/m/how_5615409_create-pdfs-using-bean.html","Parent Url":"http://www.ehow.com/mobilearticle35.xml","Redirect Chain":[{"$type":"Demand.TestFramework.Core.Entities.UrlStatus, Demand.TestFramework.Core","Status":301,"Url":"http://www.ehow.com/how_5615409_create-pdfs-using-bean.html"}]} 

Le code que je utilise pour sérialiser ressemble:

JsonConvert.SerializeObject(collection, Formatting.None, new JsonSerializerSettings 
{ 
TypeNameHandling = TypeNameHandling.Objects, 
TypeNameAssemblyFormat = System.Runtime.Serialization.Formatters.FormatterAssemblyStyle.Simple 
}); 

désérialiser que je fais:

JsonConvert.DeserializeObject<T>(collection, new JsonSerializerSettings 
{ 
TypeNameHandling = TypeNameHandling.Objects, 
TypeNameAssemblyFormat = System.Runtime.Serialization.Formatters.FormatterAssemblyStyle.Simple, 
}); 

Le dictionnaire revient bien, toutes les chaînes reviennent bien, mais la liste n'est pas désérialisée correctement. Il vient tout juste comme

{[ 
    { 
    "$type": "XYZ.TestFramework.Core.Entities.UrlStatus, XYZ.TestFramework.Core", 
    "Status": 301, 
    "Url": "/how_5615409_create-pdfs-using-bean.html" 
    } 
]} 

Bien sûr, je peux deserailize cette chaîne à nouveau et je reçois l'objet correct, mais il semble que JSON.Net aurait dû le faire pour moi. Clairement, je fais quelque chose de mal, mais je ne sais pas ce que c'est.

Répondre

43

Je pense que c'est un bug dans une ancienne version de Json.NET. Si vous n'utilisez pas déjà la dernière version, mettez-la à niveau et réessayez.

public class UrlStatus 
    { 
     public int Status { get; set; } 
     public string Url { get; set; } 
    } 


    [Test] 
    public void GenericDictionaryObject() 
    { 
     Dictionary<string, object> collection = new Dictionary<string, object>() 
     { 
      {"First", new UrlStatus{ Status = 404, Url = @"http://www.bing.com"}}, 
      {"Second", new UrlStatus{Status = 400, Url = @"http://www.google.com"}}, 
      {"List", new List<UrlStatus> 
      { 
       new UrlStatus {Status = 300, Url = @"http://www.yahoo.com"}, 
       new UrlStatus {Status = 200, Url = @"http://www.askjeeves.com"} 
      } 
      } 
     }; 

     string json = JsonConvert.SerializeObject(collection, Formatting.Indented, new JsonSerializerSettings 
     { 
     TypeNameHandling = TypeNameHandling.All, 
     TypeNameAssemblyFormat = FormatterAssemblyStyle.Simple 
     }); 

     Assert.AreEqual(@"{ 
    ""$type"": ""System.Collections.Generic.Dictionary`2[[System.String, mscorlib],[System.Object, mscorlib]], mscorlib"", 
    ""First"": { 
    ""$type"": ""Newtonsoft.Json.Tests.Serialization.TypeNameHandlingTests+UrlStatus, Newtonsoft.Json.Tests"", 
    ""Status"": 404, 
    ""Url"": ""http://www.bing.com"" 
    }, 
    ""Second"": { 
    ""$type"": ""Newtonsoft.Json.Tests.Serialization.TypeNameHandlingTests+UrlStatus, Newtonsoft.Json.Tests"", 
    ""Status"": 400, 
    ""Url"": ""http://www.google.com"" 
    }, 
    ""List"": { 
    ""$type"": ""System.Collections.Generic.List`1[[Newtonsoft.Json.Tests.Serialization.TypeNameHandlingTests+UrlStatus, Newtonsoft.Json.Tests]], mscorlib"", 
    ""$values"": [ 
     { 
     ""$type"": ""Newtonsoft.Json.Tests.Serialization.TypeNameHandlingTests+UrlStatus, Newtonsoft.Json.Tests"", 
     ""Status"": 300, 
     ""Url"": ""http://www.yahoo.com"" 
     }, 
     { 
     ""$type"": ""Newtonsoft.Json.Tests.Serialization.TypeNameHandlingTests+UrlStatus, Newtonsoft.Json.Tests"", 
     ""Status"": 200, 
     ""Url"": ""http://www.askjeeves.com"" 
     } 
    ] 
    } 
}", json); 

     object c = JsonConvert.DeserializeObject(json, new JsonSerializerSettings 
     { 
     TypeNameHandling = TypeNameHandling.All, 
     TypeNameAssemblyFormat = FormatterAssemblyStyle.Simple 
     }); 

     Assert.IsInstanceOfType(typeof(Dictionary<string, object>), c); 

     Dictionary<string, object> newCollection = (Dictionary<string, object>)c; 
     Assert.AreEqual(3, newCollection.Count); 
     Assert.AreEqual(@"http://www.bing.com", ((UrlStatus)newCollection["First"]).Url); 

     List<UrlStatus> statues = (List<UrlStatus>) newCollection["List"]; 
     Assert.AreEqual(2, statues.Count); 
    } 
    } 

Modifier, je viens de remarquer que vous avez mentionné une liste. TypeNameHandling doit être défini sur All.

Documentation: TypeNameHandling setting

+1

J'utilise 3.5 Json.NET 8. Remarque J'ai même téléchargé à nouveau le zip pour être sûr. –

+0

Juste essayé la dernière version 53965, ne fonctionnait toujours pas. –

+6

TypeNameHandling = TypeNameHandling.All était l'astuce. –