Десериализация вложенного. json объекта в c# - PullRequest
0 голосов
/ 01 мая 2020

Я пытаюсь десериализовать вложенный. json (https://ergast.com/api/f1/current/results.json) в C# из API, но я застрял. Я всюду искал решение своей проблемы и пока не нашел ничего полезного, я, вероятно, просто не знаю, как это может мне помочь, учитывая, что я новичок в c# и API в целом, а не точно самый опытный из программистов.

Я вызываю следующий метод в aspx Page_Load, где я загружаю raw. json, слегка форматирую его и десериализую в racesCollection.

private static RacesCollection GetRacesFromAPI(WebClient webClient)
        {
            String JSON = webClient.DownloadString("https://ergast.com/api/f1/current.json?callback=myParser&limit=1000");
            JObject data = FormatJSON(ref JSON);
            RacesCollection racesCollection = JsonConvert.DeserializeObject<RacesCollection>(data["MRData"]["RaceTable"].ToString());
            return racesCollection;
        }

.. Это коллекция рас

    public class RacesCollection
    {
        private List<Races> races;
        public List<Races> Races { get => races; set => races = value; }
    }

.. и это те классы, к которым я пытаюсь десериализоваться.

    public class Races
    {
        int season;
        string round;
        string url;
        string raceName;
        string date;
        string time;

        public int Season { get => season; set => season = value; }
        public string Round { get => round; set => round = value; }
        public string Url { get => url; set => url = value; }
        public string RaceName { get => raceName; set => raceName = value; }
        public string Date { get => date; set => date = value; }
        public string Time { get => time; set => time = value; }

        public Dictionary<string, Circuit> Circuit { get; set; }
        public List<Results> Results { get; set; }
    }
    public class Circuit
    {
        string circuitID;
        string circuitUrl;
        string circuitName;

        public string CircuitID { get => circuitID; set => circuitID = value; }
        public string CircuitUrl { get => circuitUrl; set => circuitUrl = value; }
        public string CircuitName { get => circuitName; set => circuitName = value; }
        public Dictionary<string, Location> Location { get; set; }
    }
    public class Results
    {
        int number;
        int position;
        int points;
        int grid;
        int laps;
        string status;
        public int Number { get => number; set => number = value; }
        public int Position { get => position; set => position = value; }
        public int Points { get => points; set => points = value; }
        public int Grid { get => grid; set => grid = value; }
        public int Laps { get => laps; set => laps = value; }
        public string Status { get => status; set => status = value; }
        public Dictionary<string, Driver> Driver { get; set; }
        public Dictionary<string, Constructor> Constructor { get; set; }
    }
    public class Driver
    {
        string driverId;
        public string DriverId { get => driverId; set => driverId = value; }
    }
    public class Constructor
    {
        string constructorId;
        public string ConstructorId { get => constructorId; set => constructorId = value; }
    }


    public class Location
    {
        float lat;
        float @long;
        string locality;
        string country;

        public float Lat { get => lat; set => lat = value; }
        public float Long { get => @long; set => @long = value; }
        public string Locality { get => locality; set => locality = value; }
        public string Country { get => country; set => country = value; }
    }

При запуске все прекрасно десериализуется, пока не достигнет Circuit, который выдает это исключение.

Newtonsoft. Json .JsonSerializationException: 'Ошибка преобразования значения "albert_park" в тип "JSONAPI.Circuit". Путь 'Races [0] .Circuit.circuitId', строка 10, позиция 34. '

Внутреннее исключение ArgumentException: Не удалось привести или преобразовать из System.String в JSONAPI.Circuit.

Буду очень признателен за любую помощь в этом вопросе.

Ответы [ 2 ]

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

В json, который вы упомянули, схема - это объект в коллекции рас, а не словарь. enter image description here Итак, пожалуйста, измените свойство Circuit в своем классе Races:

public class Races
{
    int season;
    string round;
    string url;
    string raceName;
    string date;
    string time;

    public int Season { get => season; set => season = value; }
    public string Round { get => round; set => round = value; }
    public string Url { get => url; set => url = value; }
    public string RaceName { get => raceName; set => raceName = value; }
    public string Date { get => date; set => date = value; }
    public string Time { get => time; set => time = value; }

    public Circuit Circuit { get; set; }
    public List<Results> Results { get; set; }
}

Кроме того, в опубликованном json значения lat и long свойства Location являются строками, а не десятичными числами. , Таким образом, вам может потребоваться изменить также типы данных lat и long.

Примечание о стороне, но не связанные с частными свойствами в нижнем регистре, удалите частные свойства и переименуйте publi c свойства, чтобы они соответствовали вашим json ответ. Если вы не хотите переименовывать свойства в случай верблюда, то вы можете украсить каждое свойство с помощью JsonProperty (как показано ниже для свойства Season, но то же самое относится и к другим свойствам, чтобы соответствовать json)

public class Races
{
/*  
    int season;
    string round;
    string url;
    string raceName;
    string date;
    string time;
*/
    [JsonProperty("season")]
    public int Season { get; set; }
    /*
    // or use camelcasing like below then no need use JsonProperty attribute
    public int season { get; set; }
    */
    public string Round { get; set; }
    public string Url { get; set; }
    public string RaceName { get; set; }
    public string Date { get; set; }
    public string Time { get; set; }

    public Circuit Circuit { get; set; }
    public List<Results> Results { get; set; }
}

Или вы можете использовать CamelCasePropertyNamesContractResolver:

var settings = new JsonSerializerSettings
{
    ContractResolver = new CamelCasePropertyNamesContractResolver()
};
RacesCollection racesCollection = JsonConvert.DeserializeObject<RacesCollection>(data["MRData"]["RaceTable"].ToString(), settings);
0 голосов
/ 01 мая 2020

JSON библиотеки автоматически преобразуют пары ключ-значение в ссылки на классы. Просто измените public Dictionary<string, Circuit> Circuit { get; set; } на public Circuit Circuit { get; set; }.

Это относится к словарям Location, Driver и Constructor в ваших C# объектах.

...