2010-09-17 19 views
34

Sto provando a serializzare/deserializzare un Dictionary<string, object> che sembra funzionare bene se l'oggetto è un tipo semplice ma non funziona quando l'oggetto è più complesso.Serializzazione/deserializzazione Dizionario di oggetti con JSON.NET

ho questa classe:

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

nel mio dizionario aggiungo una List<UrlStatus> con una chiave di "catena di reindirizzamento" e un paio di semplici stringhe con i tasti "Stato", "URL", "Parent Url" . La stringa che sto tornando da JSON.Net assomiglia a questo:

{"$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"}]} 

Il codice che sto usando per serializzare assomigliare:

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

deserializzare che sto facendo:

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

Il dizionario torna in ordine, tutte le stringhe tornano bene, ma l'elenco non viene deserializzato correttamente. E 'appena ritorna come

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

Certo che posso deserailize di nuovo questa stringa e ottengo l'oggetto giusto, ma sembra che JSON.Net avrebbe dovuto fare questo per me. Chiaramente sto facendo qualcosa di sbagliato, ma non so cosa sia.

risposta

43

Penso che sia un bug in una versione precedente di Json.NET. Se non stai già utilizzando la versione più recente, aggiorna e riprova.

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

Modifica, ho appena notato che hai menzionato un elenco. TypeNameHandling deve essere impostato su Tutti.

Documentazione: TypeNameHandling setting

+1

sto usando Json.NET 3,5 uscita 8. Ho anche scaricato lo zip di nuovo per essere sicuri. –

+0

Ho appena provato l'ultima build 53965, ancora non ha funzionato. –

+6

TypeNameHandling = TypeNameHandling.All era il trucco. –

Problemi correlati