我正在尝试执行一个函数,该函数返回我在 Json 文件上获得的值的总和。 为此,我创建了一个模型来反序列化 Json 文件,如下所示: 使用 System.Collections.Generic;
namespace ServerMonitoringApi.Controllers.CpuUsage.Model
{
public class Metric
{
public string __name__ { get; set; }
public string core { get; set; }
public string instance { get; set; }
public string job { get; set; }
}
public class Result
{
public Metric metric { get; set; }
public IList<object> value { get; set; }
}
public class Data
{
public string resultType { get; set; }
public IList<Result> result { get; set; }
}
public class CpuUsageResponse
{
public string status { get; set; }
public Data data { get; set; }
}
}
它适用于反序列化等。我已经测试过它。
在我的 Controller 中,我有一个返回总和并导致问题的函数:
[HttpGet("Number/{instance}&{port}")]
public async Task<double> GetNumCpuUsagePerInstance(string instance, string port)
{
string perInstanceLink = MetricApiLink + "{instance=\"" + instance + ":" + port + "\"}";
string idleModeLink = MetricApiLink +
"{mode=\"idle\",instance=\"" + instance + ":" + port + "\"}";
dynamic dataGetAll;
dynamic dataGetIdle;
using (var httpClient = new HttpClient())
{
using (var response = await httpClient
.GetAsync(perInstanceLink))
{
string apiResponse = await response.Content.ReadAsStringAsync();
dataGetAll = JsonConvert.DeserializeObject<CpuUsageResponse>(apiResponse);
}
}
using (var httpClient = new HttpClient())
{
using (var response = await httpClient
.GetAsync(idleModeLink))
{
string apiResponse = await response.Content.ReadAsStringAsync();
dataGetIdle = JsonConvert.DeserializeObject<CpuUsageResponse>(apiResponse);
}
}
double sum1 = 0;
double sum2 = 0;
NumberFormatInfo provider = new NumberFormatInfo();
provider.NumberGroupSeparator = ".";
foreach(CpuUsageResponse x in dataGetAll)
{
sum1 += Convert.ToDouble(x.data.result[1].value[1], provider);
}
return sum1;
}
我已经测试了每个功能,它们工作正常,但是当我尝试执行“Foreach”时,它不起作用并给我这个错误消息:
RuntimeBinderException: Cannot implicitly convert type 'ServerMonitoringApi.Controllers.CpuUsage.Model.CpuUsageResponse' to 'System.Collections.IEnumerable'. An explicit conversion exists (are you missing a cast?) And say that the error is in the line 123 which is:
NumberFormatInfo provider = new NumberFormatInfo();
provider.NumberGroupSeparator = ".";
/*here(line 123)->*/ foreach(CpuUsageResponse x in dataGetAll)
{
sum1 += Convert.ToDouble(dataGetAll.data.result[1].value[1], provider);
}
我的 Json 文件如下:
{
"status": "success",
"data": {
"resultType": "vector",
"result": [
{
"metric": {
"__name__": "wmi_cpu_time_total",
"core": "0,0",
"instance": "192.168.1.101:9182",
"job": "Server-monitoring-Api"
},
"value": [
1583873150.877,
"95595.25"
]
},
{
"metric": {
"__name__": "wmi_cpu_time_total",
"core": "0,1",
"instance": "192.168.1.101:9182",
"job": "Server-monitoring-Api"
},
"value": [
1583873150.877,
"103647.703125"
]
},
{
"metric": {
"__name__": "wmi_cpu_time_total",
"core": "0,2",
"instance": "192.168.1.101:9182",
"job": "Server-monitoring-Api"
},
"value": [
1583873150.877,
"94185.015625"
]
},
{
"metric": {
"__name__": "wmi_cpu_time_total",
"core": "0,3",
"instance": "192.168.1.101:9182",
"job": "Server-monitoring-Api"
},
"value": [
1583873150.877,
"102109.203125"
]
},
{
"metric": {
"__name__": "wmi_cpu_time_total",
"core": "0,4",
"instance": "192.168.1.101:9182",
"job": "Server-monitoring-Api"
},
"value": [
1583873150.877,
"96709.59375"
]
},
{
"metric": {
"__name__": "wmi_cpu_time_total",
"core": "0,5",
"instance": "192.168.1.101:9182",
"job": "Server-monitoring-Api"
},
"value": [
1583873150.877,
"102046.5625"
]
},
{
"metric": {
"__name__": "wmi_cpu_time_total",
"core": "0,6",
"instance": "192.168.1.101:9182",
"job": "Server-monitoring-Api"
},
"value": [
1583873150.877,
"98963.453125"
]
},
{
"metric": {
"__name__": "wmi_cpu_time_total",
"core": "0,7",
"instance": "192.168.1.101:9182",
"job": "Server-monitoring-Api"
},
"value": [
1583873150.877,
"89011.53125"
]
}
]
}
}
我正在尝试对索引为 1 的值求和,即 value[1]
并返回它
最佳答案
您的 JSON 由单个根对象组成,其中包含 data.result []
数组:
{
"status":"success",
"data":{
"resultType":"vector",
"result":[/* Results */]
}
}
每个结果如下所示:
{
"metric": {
"__name__": "wmi_cpu_time_total",
"core": "0,0",
"instance": "192.168.1.101:9182",
"job": "Server-monitoring-Api"
},
"value": [
1583851813.666,
"79186.65625"
]
}
因此,正如您尝试在此处执行的那样,循环遍历最外层的 JSON 容器
foreach(CpuUsageResponse x in dataGetAll)
{
sum1 += Convert.ToDouble(x.data.result[1].value[1], provider);
}
确实没有意义。如果最外层的 JSON 容器是数组,那将是明智的做法。
相反,如果您想将所有 data.result[*].value[1]
值相加为 double 结果,您可以按如下方式操作:
CpuUsageResponse dataGetAll;
// Download the apiResponse JSON string (code omitted)
dataGetAll = JsonConvert.DeserializeObject<CpuUsageResponse>(apiResponse);
var sum = dataGetAll.data.result
.Select(r => r.value[1])
.Select(s => Convert.ToDouble(s, NumberFormatInfo.InvariantInfo))
.Sum();
演示 fiddle here .
注释:
请勿不要将
dataGetAll
声明为动态
。通过这样做,您可以消除所有对代码正确性的编译时检查,并将其替换为运行时错误,例如问题中显示的 RuntimeBinderException 异常。既然您创建了一个 C# 数据模型,您就应该使用它,如果您使用了它,您会收到更清晰的编译错误:CpuUsageResponse dataGetAll; dataGetAll = JsonConvert.DeserializeObject<CpuUsageResponse>(apiResponse); double sum1 = 0; NumberFormatInfo provider = new NumberFormatInfo(); provider.NumberGroupSeparator = "."; //Compilation error (line 63, col 43): foreach statement cannot operate on variables of type 'CpuUsageResponse' because 'CpuUsageResponse' does not contain a public instance definition for 'GetEnumerator' foreach(CpuUsageResponse x in dataGetAll) { sum1 += Convert.ToDouble(x.data.result[1].value[1], provider); }
演示 fiddle #2 here .
参见 When should one use dynamic keyword in c# 4.0? ,Is the use of dynamic considered a bad practice? 和 What is the 'dynamic' type in C# 4.0 used for? 进一步讨论何时使用和不使用
动态
。您的
CpuUsageResponse
数据模型看起来对于所提供的 JSON 是正确的。而不是构建您自己的自定义
NumberFormatInfo
,你可以只使用NumberFormatInfo.InvariantInfo
。
关于c# - 无法使用C#函数从Json文件读取多个值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60620156/