Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Serializing/Deserializing Dictionary of objects with JSON.NET

Tags:

json

c#

json.net

I'm trying to serialize/deserialize a Dictionary<string, object> which seems to work fine if the object is a simple type but doesn't work when the object is more complex.

I have this class:

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

In my dictionary I add a List<UrlStatus> with a key of "Redirect Chain" and a few simple strings with keys "Status", "Url", "Parent Url". The string I'm getting back from JSON.Net looks like this:

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

The code I'm using to serialize looks like:

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

to deserialize I'm doing:

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

The Dictionary comes back fine, all the strings come back fine, but the List doesn't get properly deserialized. It just comes back as

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

Of course I can deserailize this string again and I get the correct object, but it seems like JSON.Net should have done this for me. Clearly I'm doing something wrong, but I don't know what it is.

like image 872
Dan at Demand Avatar asked Sep 17 '10 21:09

Dan at Demand


People also ask

What is serializing and deserializing JSON?

JSON is a format that encodes objects in a string. Serialization means to convert an object into that string, and deserialization is its inverse operation (convert string -> object).

Can JSON serialize dictionary?

Json can't serialize Dictionary unless it has a string key. The built-in JSON serializer in . NET Core can't handle serializing a dictionary unless it has a string key.

How do you represent a dictionary in JSON?

Introducing JSON JSON is a way of representing Arrays and Dictionaries of values ( String , Int , Float , Double ) as a text file. In a JSON file, Arrays are denoted by [ ] and dictionaries are denoted by { } .

Can we convert dictionary to JSON in C#?

Simple One-Line Answer This code will convert any Dictionary<Key,Value> to Dictionary<string,string> and then serialize it as a JSON string: var json = new JavaScriptSerializer(). Serialize(yourDictionary. ToDictionary(item => item.


1 Answers

I think that is a bug in an older version of Json.NET. If you aren't already using the latest version, upgrade and try again.

    public class UrlStatus     {       public int Status { get; set; }       public string Url { get; set; }     }       [TestMethod]     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(c, typeof(Dictionary<string, object>));        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);     }   } 

Edit, I just noticed you mentioned a list. TypeNameHandling should be set to All.

Documentation: TypeNameHandling setting

like image 172
James Newton-King Avatar answered Oct 17 '22 02:10

James Newton-King