Невозможно десериализовать текущий объект JSON (например, {"name": "value"}) в проблему типа 'System.Collections.Generi c .IList - PullRequest
0 голосов
/ 24 февраля 2020

Я хочу проанализировать файл Json с использованием модели и сохранить данные в списке, при попытке выдать следующую ошибку:

Невозможно десериализовать текущий объект JSON (например, {"name": "value"}) в тип 'System.Collections.Generi c .IList`1 [Prometheus_model.PrometheusJson]', поскольку для типа требуется массив JSON (например, [1,2,3 ]) для правильной десериализации.

Вот мой Json файл:

{
    "status": "success",
    "data": {
        "resultType": "vector",
        "result": [
            {
                "metric": {
                    "__name__": "wmi_logical_disk_free_bytes",
                    "instance": "192.168.1.71:9182",
                    "job": "prometheus",
                    "volume": "C:"
                },
                "value": [
                    1582530372.189,
                    "67817701376"
                ]
            },
            {
                "metric": {
                    "__name__": "wmi_logical_disk_free_bytes",
                    "instance": "192.168.1.71:9182",
                    "job": "prometheus",
                    "volume": "D:"
                },
                "value": [
                    1582530372.189,
                    "13367246848"
                ]
            },
            {
                "metric": {
                    "__name__": "wmi_logical_disk_free_bytes",
                    "instance": "192.168.1.71:9182",
                    "job": "prometheus",
                    "volume": "HarddiskVolume1"
                },
                "value": [
                    1582530372.189,
                    "68157440"
                ]
            },
            {
                "metric": {
                    "__name__": "wmi_logical_disk_free_bytes",
                    "instance": "192.168.1.71:9182",
                    "job": "prometheus",
                    "volume": "HarddiskVolume3"
                },
                "value": [
                    1582530372.189,
                    "365953024"
                ]
            }
        ]
    }
}

моей модели (Prometheus_model), я сгенерировал ее с помощью конвертера Json в c# (QuickType):

using System;
using System.Globalization;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;

namespace Prometheus_model
{
    public partial class PrometheusJson
    {
        [JsonProperty("status")]
        public string Status { get; set; }

        [JsonProperty("data")]
        public Data Data { get; set; }
    }

    public partial class Data
    {
        [JsonProperty("resultType")]
        public string ResultType { get; set; }

        [JsonProperty("result")]
        public Result[] Result { get; set; }
    }

    public partial class Result
    {
        [JsonProperty("metric")]
        public Metric Metric { get; set; }

        [JsonProperty("value")]
        public Value[] Value { get; set; }
    }

    public partial class Metric
    {
        [JsonProperty("__name__")]
        public string Name { get; set; }

        [JsonProperty("instance")]
        public string Instance { get; set; }

        [JsonProperty("job")]
        public string Job { get; set; }

        [JsonProperty("volume")]
        public string Volume { get; set; }
    }

    public partial struct Value
    {
        public double? Double;
        public string String;

        public static implicit operator Value(double Double) => new Value { Double = Double };
        public static implicit operator Value(string String) => new Value { String = String };
    }

    internal static class Converter
    {
        public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings
        {
            MetadataPropertyHandling = MetadataPropertyHandling.Ignore,
            DateParseHandling = DateParseHandling.None,
            Converters =
            {
                ValueConverter.Singleton,
                new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal }
            },
        };
    }

    internal class ValueConverter : JsonConverter
    {
        public override bool CanConvert(Type t) => t == typeof(Value) || t == typeof(Value?);

        public override object ReadJson(JsonReader reader, Type t, object existingValue, JsonSerializer serializer)
        {
            switch (reader.TokenType)
            {
                case JsonToken.Integer:
                case JsonToken.Float:
                    var doubleValue = serializer.Deserialize<double>(reader);
                    return new Value { Double = doubleValue };
                case JsonToken.String:
                case JsonToken.Date:
                    var stringValue = serializer.Deserialize<string>(reader);
                    return new Value { String = stringValue };
            }
            throw new Exception("Cannot unmarshal type Value");
        }

        public override void WriteJson(JsonWriter writer, object untypedValue, JsonSerializer serializer)
        {
            var value = (Value)untypedValue;
            if (value.Double != null)
            {
                serializer.Serialize(writer, value.Double.Value);
                return;
            }
            if (value.String != null)
            {
                serializer.Serialize(writer, value.String);
                return;
            }
            throw new Exception("Cannot marshal type Value");
        }

        public static readonly ValueConverter Singleton = new ValueConverter();
    }
}

Мой основной класс:

using Newtonsoft.Json;
using Prometheus_model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;

namespace Test_api.v2
{
    class Program
    {
        static async System.Threading.Tasks.Task Main(string[] args)
        {
            IEnumerable<PrometheusJson> dataG = null;

            using (var client = new HttpClient())
            {
                client.BaseAddress = new Uri("http://localhost:9090/api/v1/");
                //HTTP GET
                var responseTask = client.GetAsync("query?query=wmi_logical_disk_free_bytes");
                responseTask.Wait();
                Console.WriteLine("\n responseTask: " + responseTask);

                var result = responseTask.Result;
                Console.WriteLine("\n result: "+result);
                if (result.IsSuccessStatusCode)
                {
                    var readTask = result.Content.ReadAsAsync<IList<PrometheusJson>>();
                    readTask.Wait();
                    Console.WriteLine("\n ReadTask: " + readTask);


                    dataG = readTask.Result;
                    Console.WriteLine("\n DataG: "+dataG);
                }
                else //web api sent error response 
                {
                    //log response status here..

                    Console.WriteLine("error");
                }
            }
            Console.WriteLine("\n\n\n End");
            Console.ReadLine();
        }
    }
}

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

РЕДАКТИРОВАТЬ

Новый основной класс, который я использую (это помогает мне отлаживать проще):

using Newtonsoft.Json;
using Prometheus_model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;

namespace Test_api.v2
{
    class Program
    {
        static async System.Threading.Tasks.Task Main(string[] args)
        {
            List<PrometheusJson> dataG = new List<PrometheusJson>();
            using (var httpClient = new HttpClient())
            {
                using (var response = await httpClient
                    .GetAsync("http://localhost:9090/api/v1/query?query=wmi_logical_disk_free_bytes"))
                {
                    string apiResponse = await response.Content.ReadAsStringAsync();
                    dataG = JsonConvert.DeserializeObject<List<PrometheusJson>>(apiResponse).ToList();
                }
                Console.WriteLine(dataG);
            }
        }
    }
}

РЕДАКТИРОВАТЬ: это сработало, спасибо @XingZou, вот основной класс:

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;

namespace Test_api.v2
{
    class Program
    {
        static async System.Threading.Tasks.Task Main(string[] args)
        {
            List<PrometheusJson> dataG = new List<PrometheusJson>();
            using (var httpClient = new HttpClient())
            {
                using (var response = await httpClient
                    .GetAsync("http://localhost:9090/api/v1/query?query=wmi_logical_disk_free_bytes"))
                {
                    string apiResponse = await response.Content.ReadAsStringAsync();
                    var data = JsonConvert.DeserializeObject<PrometheusJson>(apiResponse);
                    dataG.Add(data);
                }
                Console.WriteLine(dataG);
            }
        }
    }
}

Ответы [ 2 ]

1 голос
/ 24 февраля 2020

Вам необходимо прочитать ваш ответ и десериализовать строку, как показано ниже. Для вашего сценария я использую пакет Newtonsoft, который является популярным высокопроизводительным JSON фреймворком для. NET:

if (result.IsSuccessStatusCode)
{
  var readTask = result.Content.ReadAsAsync().Result;
  readTask.Wait();
  Console.WriteLine("\n ReadTask: " + readTask);
  //Get your de-serialized JSON here into your model
  var model = JsonConvert.DeserializeObject<PrometheusJson>(readTask).ToList();
}
0 голосов
/ 25 февраля 2020

Ошибка возникает из-за того, что ваш json файл соответствует только объекту PrometheusJson вместо List<PrometheusJson>, поэтому, когда я изменяю код ниже, он работает:

List<PrometheusJson> dataG = new List<PrometheusJson>();
using (var httpClient = new HttpClient())
{
    using (var response = await httpClient
        .GetAsync("http://localhost:9090/api/v1/query?query=wmi_logical_disk_free_bytes"))
    {
        string apiResponse = await response.Content.ReadAsStringAsync();
        var data = JsonConvert.DeserializeObject<PrometheusJson>(apiResponse);
        dataG.Add(data);
    }
    Console.WriteLine(dataG);
}
...