【问题标题】:Deserialize Json an access the result反序列化 Json 并访问结果
【发布时间】:2020-07-11 20:09:12
【问题描述】:

我有这个 Json:

{
   "UpdatePack":"updatePacks\/1585654836.pack",
   "Updates":[
      {
         "Name":"MsgBoxEx",
         "version":"1.5.14.88",
         "ChangeLog":"BugFix: Form didn't resize correct.",
         "Hash":"5FB23ED83693A6D3147A0485CD13288315F77D3D37AAC0697E70B8F8C9AA0BB8"

},
      {
         "Name":"Utilities",
         "version":"2.5.1.58",
         "ChangeLog":"StringManagement updated.",
         "Hash":"05E6B3F521225C604662916F50A701E9783E13776DE4FCA27BE4B69705491AC5"

}

]
}

我创建了 2 个用于反序列化的类。

class UpdatesList
{
    public string Name { get; set; }
    public string Version { get; set; }
    public string ChangeLog { get; set; }
    public string Hash { get; set; }
}
class JsonObjectHolder
{
    public string UpdatePack { get; set; }
    //public Dictionary<int, MyData> { get; set; }
    public Dictionary<int, UpdatesList> Updates { get; set; }
}

但是当我尝试访问字典时,我不断收到Unhandled Exception: System.NullReferenceException: Object reference not set to an instance of an object. at " Console.WriteLine(jsonTest.Dict.Count);"

我是在反序列化错误,还是需要做其他事情才能访问字典的结果?

我是 C# 和 Json 的新手。

我希望有人能给我指出如何处理这个问题的正确方向。

我正在使用 Visual Studio 2019 最新更新和 .net 4.8。 问候 /LR

【问题讨论】:

  • 它不是一个集合,它只是两个属性分别为 0 和 1 的名称

标签: c# json dictionary


【解决方案1】:

您的代码不起作用,因为 01 标记只是一个属性,而不是数组项(您周围没有方括号 [])。您可以使用JObject 手动将这些值解析为所需的结构

var json = JObject.Parse(your_json_string);
var dict = new Dictionary<int, UpdatesList>();
foreach (var item in json.Properties())
{
    if (item.Value.Type == JTokenType.Object)
    {
        var index = int.Parse(item.Name);
        var updateList = item.Value.ToObject<UpdatesList>();
        dict.Add(index, updateList);
    }
}

var holder = new JsonObjectHolder
{
    UpdatePack = json["Updates"]?.Value<string>(),
    Dict = dict
};

更新:根据对 JSON 的 OP 更改,它可能会更简单地反序列化

var list = json["Updates"]?.ToObject<List<UpdatesList>>();

var holder = new JsonObjectHolder
{
    UpdatePack = json["UpdatePack"]?.Value<string>(),
    Dict = list.Select((updatesList, index) => new { updatesList, index })
                    .ToDictionary(x => x.index, x => x.updatesList)
};

这里的重点是Updates 是一个项目数组,而不是键值集合。可以使用System.Linq 中的ToDictionary 方法将其转换为Dictionary&lt;int, UpdatesList&gt;(或按原样使用List&lt;UpdatesList&gt;

【讨论】:

  • 您好,对不起。我粘贴了错误的 json,它是一个硬编码的测试代码,我用正确的 json 更新了问题。
  • @Lupus 然后你可以反序列化更新的 json 只列出,没有索引。或者手动添加它们。你需要Dictionary&lt;int, UpdatesList&gt;()吗?
【解决方案2】:

我不明白您为什么需要Dictionary&lt;int, UpdatesList&gt; Updates,因为您可以轻松地使用List&lt;Update&gt; Updates,因为您的更新位于JSON 数组中。

我会像这样为你的类建模:

public class Update
{
    public string Name { get; set; }
    public string Version { get; set; }
    public string ChangeLog { get; set; }
    public string Hash { get; set; }
}

public class RootObject
{
    public string UpdatePack { get; set; }
    public List<Update> Updates { get; set; }
}

然后你可以反序列化:

 JsonConvert.DeserializeObject<RootObject>(json);

dotnetfiddle.net 上试用一下

注意:要将 JSON 转换为 C# 类,您可以在 Visual Studio 中转到 编辑 -> 选择性粘贴 -> 将 JSON 粘贴为类。在使用它之前,请确保您已将 JSON 复制到剪贴板。您将获得与上述类似的课程。

【讨论】:

    【解决方案3】:

    您得到的异常本质上意味着在初始化对象之前正在访问该值。

    使用 NewtonSoft 是一种更好、更简单、更清洁的方法。 (您可以轻松地将其作为 Nuget 包获取)

    示例:

    public class Account
    {
        public string Email { get; set; }
        public bool Active { get; set; }
        public DateTime CreatedDate { get; set; }
        public IList<string> Roles { get; set; }
    }
    

    然后用法:

    string json = @"{
      'Email': 'james@example.com',
      'Active': true,
      'CreatedDate': '2013-01-20T00:00:00Z',
      'Roles': [
        'User',
        'Admin'
      ]
    }";
    
    Account account = JsonConvert.DeserializeObject<Account>(json);
    
    Console.WriteLine(account.Email);
    

    来源:https://www.newtonsoft.com/json/help/html/DeserializeObject.htm

    【讨论】:

    • 嗨,我确实使用 Json.Net(我应该在我的问题中添加这个,我的错),我已经阅读了 json 帮助,但遗憾的是我不够聪明,不知道该怎么做根据帮助文件。
    • 好的。请详细说明您到底在哪里遇到问题?因为上面的示例应该足以实现。您在安装 Newtonsoft 时遇到问题吗?如果是,您可以使用 Visual Studio 中的 Nuget 包管理器安装它。一个小的谷歌查询应该会给你一个安装 Nuget 包的教程。如果您遇到任何其他问题,请告诉我。我会尽力提供帮助。
    • 我无法访问该目录。当我尝试计数时,我得到了 NullExcption。
    【解决方案4】:

    您的数据和课程不兼容。如果您像这样更改字符串,它将起作用。

    将“Updates”更改为“UpdatePack”并在字典项周围添加“Dict”。

    {
       "UpdatePack":"updates\/4D1D7964D5B88E5867324F575B77D2FA.zip",
       "Dict":{
          "0":{
             "Name":"MsgBoxEx",
             "Version":"1.0.123.58",
             "ChangeLog":"Bugfix:Form didn't resize correct",
             "hash":"AA94556C0D2C8C73DD217974D252AF3311A5BF52819B06D179D17672F21049A6"
          },
          "1":{
             "Name":"Utilities",
             "Version":"1.5.321.87",
             "ChangeLog":"StringManagement updated",
             "hash":"2F561B02A49376E3679ACD5975E3790ABDFF09ECBADFA1E1858C7BA26E3FFCEF"
          }
       }
    }
    

    【讨论】:

    • 嗨,你是对的,这是我粘贴的测试代码,而不是正确的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-10-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多