【问题标题】:Serializing/Deserializing Dictionary of objects with JSON.NET使用 JSON.NET 序列化/反序列化对象字典
【发布时间】:2010-09-17 21:17:10
【问题描述】:

我正在尝试序列化/反序列化 Dictionary<string, object>,如果对象是简单类型,这似乎可以正常工作,但当对象更复杂时则无法正常工作。

我有这门课:

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

在我的字典中,我添加了一个List<UrlStatus>,其键为“重定向链”和一些简单的字符串,键为“状态”、“网址”、“父网址”。我从 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 应该为我完成此操作。显然我做错了什么,但我不知道是什么。

【问题讨论】:

    标签: c# json json.net


    【解决方案1】:

    我认为这是旧版本 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 setting

    【讨论】:

    • 我正在使用 Json.NET 3.5 Release 8。我什至再次下载了 zip 以确保。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-22
    • 1970-01-01
    相关资源
    最近更新 更多