使用JSON.NET序列化/反序列化对象字典

37
我试图对一个Dictionary<string, object>进行序列化/反序列化,如果对象是简单类型,则似乎可以正常工作,但如果对象比较复杂,则无法正常工作。
我有这个类:
public class UrlStatus
{
 public int Status { get; set; }
 public string Url { get; set; }
}
在我的字典中,我使用“Redirect Chain”作为键添加了一个类型为List<UrlStatus>的列表,以及几个带有键“Status”,“Url”,“Parent Url”的简单字符串。我从JSON.Net获取到的字符串如下所示:
{"$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"}]}

我用于序列化的代码如下:

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

我正在进行反序列化,所以我这样做:

JsonConvert.DeserializeObject<T>(collection, new JsonSerializerSettings
{
 TypeNameHandling = TypeNameHandling.Objects,
 TypeNameAssemblyFormat = System.Runtime.Serialization.Formatters.FormatterAssemblyStyle.Simple, 
});
字典的返回结果很好,所有字符串都能够良好返回,但是列表并没有得到适当的反序列化。它只是作为

返回。
{[
  {
    "$type": "XYZ.TestFramework.Core.Entities.UrlStatus, XYZ.TestFramework.Core",
    "Status": 301,
    "Url": "/how_5615409_create-pdfs-using-bean.html"
  }
]}
当然,我可以再次将这个字符串反序列化,然后获得正确的对象,但似乎 JSON.Net 应该为我完成此操作。显然,我做错了什么事情,但我不知道是什么。
1个回答

44
我认为这是一个较旧版本的Json.NET中的错误。如果您还没有使用最新版本,请升级并再次尝试。
    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);
    }
  }

编辑,我刚注意到您提到了一个列表。TypeNameHandling 应该设置为 All。

文档:TypeNameHandling 设置


1
我正在使用Json.NET 3.5 Release 8,为了确保没有问题,我甚至重新下载了zip文件。 - Dan at Demand

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接