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

问题描述 投票:0回答:1

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

反序列化等效果很好。我已经测试过。

在我的控制器中,我有此函数返回总和并引起问题:

[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:无法隐式转换类型'ServerMonitoringApi.Controllers.CpuUsage.Model.CpuUsageResponse''System.Collections.IEnumerable'。存在显式转换(你想念演员吗?)并说该错误在第123行中:

    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"
                ]
            }
        ]
    }
}
c# json rest api asp.net-core
1个回答
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]值相加成一个双精度结果,则可以如下进行:

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();

演示小提琴here

注意:

  • Do notdataGetAll声明为dynamic。这样做可以消除所有编译时检查代码正确性的问题,并将其替换为运行时错误,例如问题中显示的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);
    }   
    

    演示小提琴#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?有关何时使用和不使用dynamic的进一步讨论。

  • 您的CpuUsageResponse数据模型对于提供的JSON看起来是正确的。

  • 除了构建自己的自定义NumberFormatInfo外,您还可以使用NumberFormatInfo

© www.soinside.com 2019 - 2024. All rights reserved.