在 C# 中,如何为具有多个嵌套数组的 JSON 对象建模?

Posted

技术标签:

【中文标题】在 C# 中,如何为具有多个嵌套数组的 JSON 对象建模?【英文标题】:In C#, how do I model a JSON object with multiple nested arrays? 【发布时间】:2014-10-04 20:53:33 【问题描述】:

我正在从我正在连接的系统获取此 JSON 响应,并试图找出将其反序列化为 C# 对象的最佳方法。我目前正在使用RestSharp,这似乎很容易使用,但 JSON 的格式让我有点困惑。以下是它的格式:

[
  "name": "Tickets:",
   "schema": [
    "dataType": "string", "colName": "First", "idx": 0, 
    "dataType": "string", "colName": "Second", "idx": 1, 
    "dataType": "string", "colName": "Name", "idx": 2
   ], 
   "data": [
            ["bill", "test", "joe"],
            ["bill2", "test2", "joe2"],
            ["bill3", "test3", "joe3"]
           ]
  
] 

这是我当前的代码:

var url = "http://myUrl:10111";
var client = new RestClient  BaseUrl = url ;

var request = new RestRequest  Method = Method.GET, Resource = "/search?fmt=Json", RequestFormat = DataFormat.Json ;
request.AddHeader("accept", "application/json");

var response = client.Execute(request);
var wptResponse = new JsonDeserializer().Deserialize<TicketResults>(response);
return wptResponse;

但如上所述,我正在尝试找出对 TicketResults 对象进行建模以支持反序列化上述消息的正确方法。

理想情况下,我想要这样的东西:

 public class TicketResults
 
     public List<Ticket> Tickets get;set;
 

 public class Ticket
 
     public string First get;set;
     public string Second get;set;
     public string Name get;set;
 

在上面的示例中,Tickets 集合中将获得三个条目。

此外,上述 JSON 格式是否正常,因为我从未见过将其分解为单独的架构和数据部分(我可以看到它在哪里可以节省一些空间,但在这种情况下,消息不是那么大)

【问题讨论】:

查看 newtonsoft 库以将 json 反序列化为对象。也可以在类中的属性上方使用数据注解来映射到json属性。 问题更多是关于这个时髦的模式(相对于 RestSharp 的任何特定问题)。 是的,我之前使用过 newtonsoft 来处理一个时髦的方案,它是迄今为止最好的。只是将 OP 指向一个可能更简单的解决方案 由于生成的类中属性的数量和名称在编译时是未知的,您打算如何使用它们?即,假设当您运行代码时,REST 服务会为您提供名为“XYZ”的类的架构,该类具有“Foo”和“Bar”属性。但是为了实例化和使用这个类,你必须事先知道生成的类的名称,以及它的属性名称。 @Asad - 同意。 .我现在只是要忽略架构并假设硬编码字段(因为有人告诉我架构不会在不让我知道和更新的情况下更改 【参考方案1】:

在 Visual Studio 2012 及更高版本中,您可以转到 Edit &gt; Paste Special &gt; Paste JSON as classes。鉴于您从剪贴板粘贴的示例,它会生成以下代码。

public class Rootobject

    public Class1[] Property1  get; set; 


public class Class1

    public string name  get; set; 
    public Schema[] schema  get; set; 
    public string[][] data  get; set; 


public class Schema

    public string dataType  get; set; 
    public string colName  get; set; 
    public int idx  get; set; 


string json = File.ReadAllText("json.txt");
Rootobject root = new Rootobject();
root.Property1 = JsonConvert.DeserializeObject<Class1[]>(json);

【讨论】:

这不是 OP 想要反序列化的类。请看问题。 @Asad 刚刚对此进行了测试,它运行良好。将测试添加到我的答案中。这不仅解决了他当前 JSON 结构的问题,而且解决了将来尝试将 JSON 结构映射到类的所有问题。这就是我所说的给某人一根鱼竿而不是一条鱼。粘贴为 JSON 是一项很棒的功能,可以节省大量手动创建模型类的时间和精力。 对象上的命名已关闭(粘贴时自动生成的类的 bc),但它是相同的(我只是在我的回答中解决了对 RootObject 的需求)。此外,粘贴 JSON 的 +1 - 不知道! 真棒没看到这节省了我很多时间谢谢! 这很棒。谢谢一百万!【参考方案2】:

我同意 json 格式相当……愚蠢。以下是如何为您的 dto 建模:

    public class JsonDto
    
        public string name  get; set; 
        public Schema[] schema get; set;
        public string[][] data  get; set; 
    
    public class Schema
    
        public string dataType  get; set; 
        public string colName  get; set; 
        public int idx  get; set; 
    

我能够让您的字符串(未更改)使用JSON.Net 反序列化,如下所示:

var jsonDto = JsonConvert.DeserializeObject<JsonDto[]>(json);

如果您仍有问题,请告诉我。

【讨论】:

当我使用上面的这个数据结构时,我得到以下错误:无法将“RestSharp.JsonArray”类型的对象转换为“System.Collections.Generic.IDictionary`2[System.String,System .Object]'. 我不得不返回 List (即使列表中总是只有 1 个项目。 我测试了这个解决方案。它按照这个答案中的建议工作。 @leora 是的,请注意 DeserializeObject&lt;JsonDto[]&gt; - 特别是 JsonDto[]。这是 json 的愚蠢(是一个词吗?)的一部分——即使数组中只有一个对象,根元素也是一个数组。【参考方案3】:

您对返回的 JSON 的结构有任何控制权吗?这有点古怪。由于某种原因,字段名称和数据被分离出来。如果格式更合理一点,例如:

[
    
        "First": "bill",
        "Second": "test",
        "Name": "joe"
    ,

    
        "First": "bill2",
        "Second": "test2",
        "Name": "joe2"
    ,
]

然后您可以将其序列化到您的 Ticket 类。但是,如果不修改 JSON 结构(我不建议您这样做),您要序列化到的 C# 类将必须与 JSON 结构匹配。

我想你可以想出一个中间类来保存你收到的 JSON 数据。然后您可以遍历这些对象并从中创建 Ticket 类的实例。至少这样你最终得到了一个你可以使用的数据结构。

【讨论】:

很遗憾,我无法控制格式

以上是关于在 C# 中,如何为具有多个嵌套数组的 JSON 对象建模?的主要内容,如果未能解决你的问题,请参考以下文章

C# Object to Json to Xml,如何为数组项生成xml元素

如何为 C# 字典中的多个键分配一个值?

使用 C# 在复杂的 JSON 数组中查找和打印重复项

如何为嵌套 JSON 中存在 JSON 列表的嵌套 JSON 创建模型?

如何为来自 SpringBoot 后端代码的嵌套 JSON 响应在 angular8(TypeScript) 或更高版本中定义模型类

如何为包含特定函数数组的 JSON 对象编写接口