Search code examples
c#jsonjson.net

How to fix Newtonsoft.Json.JsonSerilizationException?


I get this exception:

Newtonsoft.Json.JsonSerializationException: "Cannot deserialize the current JSON array (e.g. [1,2,3]) into type 'WeatherApiClass.Weather' because the type requires a JSON object (e.g. {"name":"value"}) to deserialize correctly. To fix this error either change the JSON to a JSON object (e.g. {"name":"value"}) or change the deserialized type to an array or a type that implements a collection interface (e.g. ICollection, IList) like List that can be deserialized from a JSON array. JsonArrayAttribute can also be added to the type to force it to deserialize from a JSON array. Path 'weather', line 1, position 50."*

This happen when i'm trying request city's data of weather.

My WeatherApi Code:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using Telegram.Bot;
using Telegram.Bot.Args;
using Telegram.Bot.Types.Enums;
using Telegram.Bot.Types.ReplyMarkups;
using Telegram.Bot.Types;
using Xunit;
using Xunit.Abstractions;
using Xunit.Sdk;
using Microsoft.Extensions.Configuration;
using System.Net;
using Json.Net;
using Newtonsoft.Json;

namespace WeatherApiClass
{
    public class WeatherApi
    {
        public static string api_token = "weatherapi_token";
        public string inputCityName;
        public static string nameCity;
        internal static float temperatureCity;
        internal static string weatherCity;
        internal static string answer;
        internal static float visibilityCity;
        internal static int pressureCity;
        internal static string countryCity;
        internal static int humidityCity;
        public static void Weather(string city_name)
        {
            try
            {
                string url = "https://api.openweathermap.org/data/2.5/weather?q=" + city_name + "&appid=" + api_token;
                HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(url);
                HttpWebResponse webResponse = (HttpWebResponse)webRequest?.GetResponse();
                string WeathResponse;

                using (StreamReader streamReader = new StreamReader(webResponse.GetResponseStream()))
                {
                    WeathResponse = streamReader.ReadToEnd();
                }
                
                WeatherResponse weatherResponse = JsonConvert.DeserializeObject<List<WeatherResponse>>(WeathResponse)[0];

                nameCity = weatherResponse.Name;
                temperatureCity = weatherResponse.Main.Temp - 273;
                weatherCity = weatherResponse.weather.Main;
                visibilityCity = weatherResponse.Visibility / 1000;
                pressureCity = weatherResponse.Pressure;
                countryCity = weatherResponse.Country;
                humidityCity = weatherResponse.Humidity;
            }
            catch (System.Net.WebException)
            {
                Console.WriteLine("Error to connect with home.openweathermap.org");
                return;
            }
        }


        public static void Celsius(float celsius)
        {
            if (celsius == 0)
            {
                answer = "answer";
            }
            else if (celsius >= -14 & celsius < -4)
            {
                answer = "answer";
            }
            else if (celsius <= 10 & celsius < 18)
            {
                answer = "answer";
            }
            else if (celsius <= 18)
            {
                answer = "answer";
            }
            else if (celsius >= 20 & celsius <= 25)
            {
                answer = "answer";
            }
            else if (celsius > 25)
            {
                answer = "answer";
            }


        }
    }


    public class WeatherResponse
    {
        public TemperatureInfo Main { get; set; }

        public string Name { get; set; }

        public Weather weather { get; set; }

        public float Visibility { get; set; }

        public int Pressure { get; set; }
        
        public string Country { get; set; }
        
        public int Humidity { get; set; }
    }

    public class Weather
    {
        public string Main { get; set; }
    }
    public class TemperatureInfo
    {
        public float Temp { get; set; }
    }
}

Json from api.openweather.org:

{
   "coord":{
      "lon":-0.1257,
      "lat":51.5085
   },
   "weather":[
      {
         "id":802,
         "main":"Clouds",
         "description":"scattered clouds",
         "icon":"03d"
      }
   ],
   "base":"stations",
   "main":{
      "temp":298.92,
      "feels_like":298.94,
      "temp_min":296.73,
      "temp_max":301.06,
      "pressure":1014,
      "humidity":53
   },
   "visibility":10000,
   "wind":{
      "speed":5.14,
      "deg":250
   },
   "clouds":{
      "all":40
   },
   "dt":1658321995,
   "sys":{
      "type":2,
      "id":2075535,
      "country":"GB",
      "sunrise":1658290010,
      "sunset":1658347589
   },
   "timezone":3600,
   "id":2643743,
   "name":"London",
   "cod":200
}

Solution

  • try this, instead of list of WeatherResponse you have to use just WeatherResponse, instead of Weather use List < Weather >

    WeatherResponse weatherResponse = JsonConvert.DeserializeObject<WeatherResponse>(WeathResponse);
    

    classes

    public class WeatherResponse
    {
        public Coord coord { get; set; }
        public List<Weather> weather { get; set; }
        public string @base { get; set; }
        public Info main { get; set; }
        public int visibility { get; set; }
        public Wind wind { get; set; }
        public Clouds clouds { get; set; }
        public int dt { get; set; }
        public Sys sys { get; set; }
        public int timezone { get; set; }
        public int id { get; set; }
        public string name { get; set; }
        public int cod { get; set; }
    }
    public class Clouds
    {
        public int all { get; set; }
    }
    
    public class Coord
    {
        public double lon { get; set; }
        public double lat { get; set; }
    }
    
    public class Info
    {
        public double temp { get; set; }
        public double feels_like { get; set; }
        public double temp_min { get; set; }
        public double temp_max { get; set; }
        public int pressure { get; set; }
        public int humidity { get; set; }
    }
    
    
    
    public class Sys
    {
        public int type { get; set; }
        public int id { get; set; }
        public string country { get; set; }
        public int sunrise { get; set; }
        public int sunset { get; set; }
    }
    
    public class Weather
    {
        public int id { get; set; }
        public string main { get; set; }
        public string description { get; set; }
        public string icon { get; set; }
    }
    
    public class Wind
    {
        public double speed { get; set; }
        public int deg { get; set; }
    }