Как получить последний элемент в JSON в C# - PullRequest
0 голосов
/ 30 мая 2020

Я пытаюсь получить одно значение из ответа JSON от Azure Rest API.

Ниже мой код, в котором я смог добраться до окончательного массива, но не смог получить последний элемент из этого массива.

            string token = await GetAccessToken(GMETenantID, GMEClientID, GMEAppKey);

            var httpClient = new HttpClient
            {
                BaseAddress = new Uri("https://management.azure.com/subscriptions/")
            };
            string URI = $"/subscriptions/{SubscriptionGUID}/providers/Microsoft.Storage/storageAccounts?api-version=2019-06-01";

            httpClient.DefaultRequestHeaders.Remove("Authorization");
            httpClient.DefaultRequestHeaders.Add("Authorization", "Bearer " + token);
            HttpResponseMessage response = await httpClient.GetAsync(URI).ConfigureAwait(false);

            var HttpsResponse = await response.Content.ReadAsStringAsync();
            dynamic Result = JsonConvert.DeserializeObject<object>(HttpsResponse);

            foreach (dynamic item in Result["value"])
            {
                string StorageID = item.id;
                string StorageAccountName = item.name;
                string ResourceType = item.type;

                int CharsToRemove = 12 + ResourceType.Length + StorageAccountName.Length;

                string ResourceGroupName = StorageID.Remove(0,67);
                ResourceGroupName = ResourceGroupName.Remove(ResourceGroupName.Length - CharsToRemove);

                string StartTime = DateTime.Now.AddDays(-7).ToString("yyyy-MM-ddTHH:mm:ss") + "Z"; ;
                string EndTime = DateTime.Now.ToString("yyyy-MM-ddTHH:mm:ss") + "Z";

                var BlobhttpClient = new HttpClient
                {
                    BaseAddress = new Uri("https://management.azure.com/subscriptions/")
                };

                string BlobURI = $"/subscriptions/{SubscriptionGUID}/resourceGroups/{ResourceGroupName}/providers/{ResourceType}/{StorageAccountName}/blobServices/default/providers/microsoft.insights/metrics?timespan={StartTime}/{EndTime}&aggregation=average&metricnames=BlobCapacity&api-version=2018-01-01";
                BlobhttpClient.DefaultRequestHeaders.Remove("Authorization");
                BlobhttpClient.DefaultRequestHeaders.Add("Authorization", "Bearer " + token);
                HttpResponseMessage Blobresponse = await httpClient.GetAsync(BlobURI).ConfigureAwait(false);
                var BlobHttpsResponse = await Blobresponse.Content.ReadAsStringAsync();

                dynamic value = JObject.Parse(BlobHttpsResponse);

                foreach (dynamic List1 in value["value"])
                {
                    foreach (dynamic List2 in List1["timeseries"])
                    {
                        foreach (dynamic List3 in List2["data"])
                        {
                            Console.WriteLine((long?)List3["average"]);
                        }
                    }
                }
            }
            Console.ReadLine();

Я также считаю, что должен быть более простой способ получить это одно значение вместо использования 3 циклов Foreach.

HttpsResponse: (В фактическом ответе есть 168 меток времени и средних значений, но я поставил только 3 значения)

{
  "cost": 0,
  "timespan": "2020-05-22T03:04:46Z/2020-05-29T03:04:46Z",
  "interval": "PT1H",
  "value": [
    {
      "id": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/MyResourceGroupName/providers/Microsoft.Storage/storageAccounts/MyAstorageAccountName/blobServices/default/providers/Microsoft.Insights/metrics/BlobCapacity",
      "type": "Microsoft.Insights/metrics",
      "name": {
        "value": "BlobCapacity",
        "localizedValue": "Blob Capacity"
      },
      "displayDescription": "The amount of storage used by the storage account's Blob service in bytes.",
      "unit": "Bytes",
      ".timeseries": [
        {
          "metadatavalues": [],
          "data": [
            {
              "timeStamp": "2020-05-22T03:04:00Z",
              "average": 586904516140.0
            },
            {
              "timeStamp": "2020-05-22T04:04:00Z",
              "average": 587058965680.0
            },
            {
              "timeStamp": "2020-05-22T05:04:00Z",
              "average": 587058965680.0
            }
          ]
        }
      ],
      "errorCode": "Success"
    }
  ],
  "namespace": "Microsoft.Storage/storageAccounts/blobServices",
  "resourceregion": "eastus2"
}

Все, что я хочу, это номер 587058965680, который является последним значением JSON и самой последней меткой времени.

В значительной степени я хочу получить точный результат, как я получаю ниже код PowerShell. PowerShell работает как шарм в 4 строки, но мне пришлось написать так много строк в C#

$StorageAccounts = Get-AzStorageAccount -ResourceGroupName "My ResourceGroupName"

$StorageAccountID = $StorageAccounts.ID + "/blobServices/default"
$Start = (get-date).AddDays(-7)
$End = get-date

$Metric = Get-AzMetric -ResourceId $StorageAccountID -MetricName "BlobCapacity" -StartTime $Start -EndTime $End  -WarningAction Ignore

$ContainerSize = ($Metric.Data | sort-object -Descending Average | Select-Object -First 1).Average/1024/1024/1024

Ответы [ 3 ]

0 голосов
/ 30 мая 2020

Использование Newtonsoft.Json.Linq может быть полезным в этом конкретном случае.

Например:


IList<long> averages = 
    value["value"].SelectMany(val => val[".timeseries"]
                  .SelectMany(tm => tm["data"]
                  .Select(ave => (long) ave["average"]))).ToList();

Вывод:

[0] 586904516140
[1] 587058965680
[2] 587058965680
0 голосов
/ 30 мая 2020

Я как-то решил это странным логом c:)

string token = await GetAccessToken(GMETenantID, GMEClientID, GMEAppKey);

            var httpClient = new HttpClient
            {
                BaseAddress = new Uri("https://management.azure.com/subscriptions/")
            };
            string URI = $"/subscriptions/{SubscriptionGUID}/providers/Microsoft.Storage/storageAccounts?api-version=2019-06-01";

            httpClient.DefaultRequestHeaders.Remove("Authorization");
            httpClient.DefaultRequestHeaders.Add("Authorization", "Bearer " + token);
            HttpResponseMessage response = await httpClient.GetAsync(URI).ConfigureAwait(false);

            var HttpsResponse = await response.Content.ReadAsStringAsync();
            dynamic Result = JsonConvert.DeserializeObject<object>(HttpsResponse);

            foreach (dynamic item in Result["value"])
            {
                string StorageID = item.id;
                string StorageAccountName = item.name;
                string ResourceType = item.type;

                int CharsToRemove = 12 + ResourceType.Length + StorageAccountName.Length;

                string ResourceGroupName = StorageID.Remove(0,67);
                ResourceGroupName = ResourceGroupName.Remove(ResourceGroupName.Length - CharsToRemove);

                string StartTime = DateTime.Now.AddDays(-7).ToString("yyyy-MM-ddTHH:mm:ss") + "Z"; ;
                string EndTime = DateTime.Now.ToString("yyyy-MM-ddTHH:mm:ss") + "Z";

                var BlobhttpClient = new HttpClient
                {
                    BaseAddress = new Uri("https://management.azure.com/subscriptions/")
                };

                string BlobURI = $"/subscriptions/{SubscriptionGUID}/resourceGroups/{ResourceGroupName}/providers/{ResourceType}/{StorageAccountName}/blobServices/default/providers/microsoft.insights/metrics?timespan={StartTime}/{EndTime}&aggregation=average&metricnames=BlobCapacity&api-version=2018-01-01";
                BlobhttpClient.DefaultRequestHeaders.Remove("Authorization");
                BlobhttpClient.DefaultRequestHeaders.Add("Authorization", "Bearer " + token);
                HttpResponseMessage Blobresponse = await httpClient.GetAsync(BlobURI).ConfigureAwait(false);
                var BlobHttpsResponse = await Blobresponse.Content.ReadAsStringAsync();

                dynamic value = JObject.Parse(BlobHttpsResponse);
                long FinalValue = 0;
                foreach (dynamic List1 in value["value"])
                {
                    foreach (dynamic List2 in List1["timeseries"])
                    {
                        foreach (dynamic List3 in List2["data"])
                        {                            
                            if (List3["average"] != null)
                            {
                                long NewData = List3["average"];
                                
                                if (NewData > FinalValue)
                                {
                                    FinalValue = NewData;
                                }
                                else if (NewData > FinalValue)
                                {
                                    FinalValue = NewData;
                                }

                            }
                        }
                    }
                }
                Console.WriteLine(""); 
                Console.WriteLine(FinalValue);
                Console.WriteLine($"Done with StorageAccount: {StorageAccountName}");                
            }
            Console.ReadLine();
0 голосов
/ 30 мая 2020

Создайте для него простую модель:

public class Data
{
    [JsonProperty("timeStamp")]
    public DateTime TimeStamp { get; set; }

    [JsonProperty("average")]
    public decimal Average { get; set; }
}

Теперь просто используйте JObject для перехода к клавише data в json и десерилизуйте ее.

var jObj = JObject.Parse(json);
var data = jObj["value"][0][".timeseries"][0]["data"].ToString();
var dataList = JsonConvert.DeserializeObject<IEnumerable<Data>>(data);

Затем вы можете использовать Linq для получения последнего элемента в массиве:

var last = dataList.Last();

Если вы не хотите использовать Models, вы можете напрямую доступ к значениям с помощью JObject

Итак, вы можете сделать это напрямую:

var jObj = JObject.Parse(json);
var data = jObj["value"][0][".timeseries"][0]["data"].Last();
var avg = data["average"];
...