【问题标题】:Deserializing JSON Without Unique Property Name反序列化没有唯一属性名称的 JSON
【发布时间】:2018-04-20 02:23:07
【问题描述】:

我有一个如下所示的 json 字符串

{
    "1ST": {
        "name": "One",
        "symbol": "1st"
    },
    "2ND": {
        "name": "Two",
        "symbol": "2nd"
    }
}

我正在尝试将其序列化为 C# 对象。看起来它正在创建一个字典,所以我创建了以下结构

public class Response
{
    public Dictionary<string, Item> Objects { get; set; }
}

public class Item
{
    public string name { get; set; }
    public string symbol { get; set; }
}

在序列化过程中运行以下

response = JsonConvert.DeserializeObject<Response>(jsonString);

它不会在反序列化时引发错误,但我的响应只是返回为空。我错过了什么?

【问题讨论】:

    标签: c# json json.net json-deserialization


    【解决方案1】:

    您有正确的基本想法,但您有一个额外的Objects 属性,您并不真正想要:您的 JSON 字典,实际上。您可以将其直接反序列化为Dictionary&lt;string, Item&gt;&gt;。这是一个例子:

    using System;
    using System.Collections.Generic;
    using System.IO;
    using Newtonsoft.Json;
    
    public class Item
    {
        public string Name { get; set; }
        public string Symbol { get; set; }
    
        public override string ToString() => $"{Name}/{Symbol}";
    }
    
    public class Test
    {
        static void Main()
        {
            var json = File.ReadAllText("test.json");
            var dictionary = JsonConvert.DeserializeObject<Dictionary<string, Item>>(json);
            foreach (var entry in dictionary)
            {
                Console.WriteLine($"{entry.Key}: {entry.Value}");
            }
        }
    }
    

    输出:

    1ST: One/1st
    2ND: Two/2nd
    

    现在如果您需要您的Response 类型,有多种选择:

    • 使其派生自 Dictionary&lt;string, Item&gt; 并删除 Objects 属性。 (如果您需要 Objects 属性,那就不好了。)
    • 反序列化到字典,然后创建一个新的Response 对象并自己分配属性。 (如果响应是另一种类型的一部分,则不好。)
    • 调查是否有一些属性让 Json.NET 将 Objects 视为一种“根”属性。

    我在最后一个方面有一些运气,但不是一个完整的解决方案。如果您将Objects 更改为Dictionary&lt;string, JToken&gt;,那么您可以将[JsonExtensionData] 应用到它,这使它成为任何不匹配属性的默认字典。但是,我还没有找到说服 Json.NET 使用该属性 执行适当转换的方法。您可以创建一个字典,每次将条目添加到其中时执行从 JTokenItem 的转换(使用常规 Json.NET 代码),然后将该值添加到另一个字典中 - 但这很丑陋。这可能只是 Json.NET 无法处理的一种情况。

    【讨论】:

      【解决方案2】:

      建议使用强类型对象,但另一种方法是您可以使用将在运行时评估的动态类型。

      请看下面的代码。

      请注意,我更改了变量名,因为我们无法在 C# 中定义以数字开头的变量。

      using Newtonsoft.Json;
      
      namespace ConsoleApplication1
      {
          class Program
          {
              static void Main(string[] args)
              {
                  var jsonString = @"{
                                  'First': {
                                      'name': 'One',
                                      'symbol': '1st'
                                  },
                                  'Second': {
                                      'name': 'Two',
                                      'symbol': '2nd'
                                  }
                              }";
      
                  //If you want to access using strong type.
                  var response = JsonConvert.DeserializeObject<Response>(jsonString);
                  var secondSymbol = response.Second.symbol.ToString();
                  System.Console.WriteLine(secondSymbol);
      
                  //If you want to access using dynamic type, will evalute in runtime.
                  var responseDynamic = JsonConvert.DeserializeObject<dynamic>(jsonString);
                  var secondSymbolDynamic = responseDynamic.Second.symbol.ToString() ;
                  System.Console.WriteLine(secondSymbolDynamic);
      
                  System.Console.ReadLine();
              }
      
              public class Response
              {
                  public Item First { get; set; }
                  public Item Second { get; set; }
              }
      
              public class Item
              {
                  public string name { get; set; }
                  public string symbol { get; set; }
              }
          }
      }
      

      希望它有用。 :)

      【讨论】:

      • "您的 JSON 文件包含 2 个对象 1st 和 2nd Object ,您无法将其映射到字典。" Json.NET 非常乐意这样做。
      • 请注意,您的答案仍然在“完全动态”和“完全静态”之间徘徊。如果只有属性名称不同,我认为使用Dictionary&lt;string, Item&gt; 非常有意义 - 我的回答显示了如何做到这一点。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-01-01
      • 1970-01-01
      • 2017-09-15
      • 1970-01-01
      • 2016-01-14
      • 1970-01-01
      相关资源
      最近更新 更多