c# - 使用 C# 解析嵌套的 Json 数据。无法访问内部元素消耗
问题描述
我最多可以解析一个嵌套级别,但我无法弄清楚如何读取consumption_history
. 我一直在尝试不同的方法来做到这一点,但无法获得消费价值。
我可以访问miu_id
andmeter_number
但不能访问consumption_list
.
模型:
class JsonModel
{
public class Rootobject
{
public string site_id { get; set; }
public Endpoint[] endpoints { get; set; }
public Paging paging { get; set; }
}
public class Paging
{
public int page { get; set; }
public int limit { get; set; }
public int total { get; set; }
public string next { get; set; }
public object prev { get; set; }
public string self { get; set; }
}
public class Endpoint
{
public string miu_id { get; set; }
public string meter_number { get; set; }
public Consumption_History[] consumption_hist { get; set; }
}
public class Consumption_History
{
public DateTime reading_date { get; set; }
public float consumption { get; set; }
public float consumption_with_multiplier { get; set; }
}
}
程序:
static void Main(string[] args)
{
string json = File.ReadAllText(@"C:\Users\ConsoleApp3\apidataone.json");
var results = JsonConvert.DeserializeObject<JsonModel.Rootobject>(json);
JsonModel.Rootobject rootobject = JsonConvert.DeserializeObject<JsonModel.Rootobject>(json);
rootobject.endpoints = JsonConvert.DeserializeObject<JsonModel.Rootobject>(json).endpoints;
foreach (JsonModel.Consumption_History ch in rootobject.endpoints)
{
Console.WriteLine(ch.consumption);
}
}
json数据:
{
"site_id":"1",
"endpoints":
[{
"miu_id":"111",
"meter_number":"88",
"consumption_history":
[{
"reading_date":"2010-02-17T00:00:00",
"consumption":1.0,
"consumption_with_multiplier":1.0
}]
}]
}
解决方案
我已经稍微简化了代码,而不是从文件中读取,我只是将 JSON 内容放在适当的位置。此代码使用Newtonsoft.Json(可通过 NUGET 包获得),但它的工作方式与其他序列化程序相同。
// using Newtonsoft.Json;
void Main()
{
string json = @"{
'site_id':'1',
'endpoints':
[{
'miu_id':'111',
'meter_number':'88',
'consumption_history':
[{
'reading_date':'2010-02-17T00:00:00',
'consumption':1.0,
'consumption_with_multiplier':1.0
}]
}]
}";
dynamic j = JsonConvert.DeserializeObject<dynamic>(json);
string site_id = j["site_id"].ToString();
var endpoints = j["endpoints"];
foreach (var endpoint in endpoints)
{
string miu_id = endpoint["miu_id"];
miu_id.Dump();
// ...
var consumption_histories = endpoint["consumption_history"];
foreach(var consumption in consumption_histories)
{
string reading_date = consumption["reading_date"];
reading_date.Dump();
// ...
} // foreach
} // foreach
}
关于JSON:只要[ ... ]
JSON 结构中有一个,这意味着有一个数组({ ... }
代表一个对象) - 并且[{ ... }]
是一个数组内的对象;属性和数组元素都用逗号 ( ,
) 分隔;字符串和属性名称需要用单引号 ( '...'
) 括起来。赋值是用冒号 ( :
) 完成的。在 JSON 中,您有对象、字符串或数字数据——这些是唯一存在的类型。如果您需要类型,则必须自己将属性转换为正确的类型。
您可以通过索引器(如循环endpoints[i]
内部for
)访问数组,或者 - 正如我假设的那样 - 您想要遍历每个元素,在这种情况下foreach
循环更容易。
注意:for
要在循环中使用它(例如for (int i = 0; i < endpointsLength; i++) { ... }
),您必须将其endpoints
转换consumption_histories
为数组类型(例如 via var endpoints = (object[])j["endpoints"];
)并失去提供的简单性dynamic
(例如,您需要一个索引器来访问一个像(endpoints[i])["miu_id"]
能够得到miu_id
) 的值。
在这种情况下,关键字dynamic
简化了很多事情,这样您就可以保持 C# 代码的“JavaScript 风格”(记住 JSON 来自 JavaScript 世界)。
如果你想引入你在 C# 中声明的类,这也是可以的。例如:
foreach (Consumption_History consumption in consumption_histories)
{
string reading_date = consumption.reading_date.ToString();
reading_date.Dump();
// ...
} // foreach
您可以看到,reading_date
现在作为 C# 属性访问,并且因为它是 type DateTime
,所以您需要先将其转换为字符串。这种转换需要在foreach
循环之前完成,因此您可以将类中的数据类型更改为字符串以避免这种情况,或者您可以使用上面显示的原始代码并将数据复制 + 转换为对象的类型化版本(例如将字符串转换为日期时间,您可以检查一下)。
如果您依赖 NewtonSoft.JSON 提供的内置转换,您可以简单地使用JsonConvert.DeserializeObject<Rootobject>(json)
而不是JsonConvert.DeserializeObject<dynamic>(json)
. 请注意,隐式转换可能会引发异常。
此外,请确保 C# 和 JSON 文件中的属性名称完全匹配 - 如果不是,您可以在 C# 中使用属性来装饰它们(有关如何执行此操作的说明,请参见此处) - xdtTransform发现它与consumption_hist
, 和在评论中提到了它。
推荐阅读
- c++ - 为什么我无法将浮点和整数值写入二进制文件 c++?
- html - HTML5 音频元素样式怪异
- flutter - Flutter 的视频通话 sdk
- web-scraping - 为什么我的网页抓取程序没有解析任何内容?
- json - 使用 Scala Play 框架构建 jsonpath
- arrays - 在 Julia 中对数组的条件赋值进行基准测试
- r - 在r中重写表/数据框
- c# - 泛型类型的 C# 强类型等效项,其中 SomeClass
和 SomeClass 是相同的 - reactjs - 如何在这些代码中执行正确的 useState?
- python - 当有重复的时间戳时如何在熊猫中过滤数据框的时间戳