【问题标题】:C# Json.Net - How to deserialize an array of objects containing an array of other objectsC# Json.Net - 如何反序列化包含其他对象数组的对象数组
【发布时间】:2019-03-22 11:04:41
【问题描述】:

从http服务器接收到的Json数据是这样的:

[
   {
      "token":"NlhYnzF0xqG"
   },
   [
      {
         "ts":"2019-03-21 14:06:22.123",
         "id":"CC_RTC_Second",
         "val":"22"
      },
      {
         "ts":"2019-03-21 14:06:00.096",
         "id":"CC_RTC_Minute",
         "val":"6"
      },
      {
         "ts":"2019-03-21 14:00:00.276",
         "id":"CC_RTC_Hour",
         "val":"14"
      }
   ]
]

我尝试了 Newtonsoft.Json 文档中介绍的一些技术,但我找不到正确的方法。我花了两天时间测试 StackOverflow 答案中的解决方案,但没有成功。

在这种特殊情况下我应该使用哪些 C# 类型和技术?

数据结构可以变化:
完整的属性列表是:td、id、val、flags、type、uts、nr。
它们都是字符串。
如果attrs不存在,服务器可以省略,例如我只能获取ts + id。
有什么方法可以处理这样的数据吗?

【问题讨论】:

  • 声明类来保存你的属性,然后反序列化为那些。您的问题不清楚,您能告诉我们您的尝试吗?
  • 您很可能需要一个自定义反序列化器,或者您最终会得到对象/动态类型,因为您有一个包含 1 个对象和 1 个数组的数组,所以您可以不要在此处创建List<T>,因为对于不同的元素,您有不同的T。
  • 如果只使用一个对象 ts+id+val,我可以使用:
  • 您可以使用JsonConvert.DeserializeObject<JToken>(json).Select(token => token is JArray ? (object)token.ToObject<List<Other>>() : (object)token.ToObject<TokenData>()),替换为正确的类型。

标签: c# arrays json object


【解决方案1】:

首先,您的 json 非常复杂,并且为您的 json 创建类层次结构是一项繁琐的工作,

但一种简单的方法是,如果您将 JSON 解析为 JArray 然后采用

  • 一个类的第 0 个元素
  • 剩下的都在另一个类的列表中

那么你可能可以检索所有的 json 数据

string json = File.ReadAllText(@"Path to your json");

JArray jArray = JArray.Parse(json);

Token token = jArray[0].ToObject<Token>();
jArray.RemoveAt(0);
RandomData[] tokenData = jArray.First.ToObject<RandomData[]>();

//--------------------Print Data to Console-------------------

Console.WriteLine(token.token + "\n");

foreach (var item in tokenData)
{
    Console.WriteLine("ts: " + item.ts);
    Console.WriteLine("id: " + item.id);
    Console.WriteLine("val: " + item.val + "\n");
}

Console.ReadLine();

类是,

class Token
{
    public string token { get; set; }
}

class RandomData
{
    public string ts { get; set; }
    public string td { get; set; }
    public string id { get; set; }
    public string val { get; set; }
    public string flags { get; set; }
    public string type { get; set; }
    public string uts { get; set; }
    public string nr { get; set; }
}

输出:

注意:您需要安装NewtonSoft NuGet 包并将using Newtonsoft.Json.Linq; 命名空间导入您的程序。

【讨论】:

  • 您的回答完全解决了我的问题。谢谢你:)
【解决方案2】:

有我的答案:

var strData = @"[{
         'token': 'NlhYnzF0xqG'
       },
       [{
         'ts': '2019-03-21 14:06:22.123',
         'id': 'CC_RTC_Second',
         'val': '22'
       }, {
         'ts': '2019-03-21 14:06:00.096',
         'id': 'CC_RTC_Minute',

       }, {

         'id': 'CC_RTC_Hour',
         'val': '14'
       }]
     ]";   
        var result = JsonConvert.DeserializeObject<List<JToken>>(strData);
        var tokens = result.Where( x=> x.Type == JTokenType.Object).Select(x=> x.ToObject<Token>());
        var innerData = result.Where(x => x.Type == JTokenType.Array).Select(x => x.ToObject<List<InnerData>>());

有类:

 public class Token
        {
             public string token { set; get; }
        }
    public class InnerData
        {
            public string ts { set; get; }
            public string id { set; get; }
            public string val { set; get; }    
        }

您可以像之前提到的那样打印结果:

foreach (var token in tokens)
{
    Console.WriteLine("ts: " + token.token);
}

【讨论】:

  • 感谢您的回答,但恐怕我无法使用生成的变量。查询对我来说是新的,我不知道如何打印令牌和 innerData 中包含的数据。非常感谢您的帮助。
  • 您可以像之前提到的那样打印 linq 结果。我添加它以发布答案
猜你喜欢
  • 1970-01-01
  • 2018-03-20
  • 1970-01-01
  • 2015-06-11
  • 2021-10-05
  • 1970-01-01
  • 2013-12-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多