c# - 无法使用C#函数从Json文件读取多个值

标签 c# json rest api asp.net-core

我正在尝试执行一个函数,该函数返回我在 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/

相关文章:

java - 构建新应用程序 : Java jax-rs ee6 restful web service with a html5 front-end using backbone. js

c# - 什么会导致进程停止重新创建?

c# - 从 C++ 调用 C# 函数是否创建编译代码

c# - 如何使用 FluorineFx 从客户端发布音频流?

RESTful 多对多可能吗?

javascript - 适用于所有组合的 JSON faker

c# - Visual Studio 2013 在创建新表时崩溃

php - 带有特殊字符的 Json_decode

c# - 绑定(bind) WebGrid 表单 AJAX

ios - JSON 查询不起作用