1
votes

I'm new to json and I am trying to parse some weather data. All is well except for one piece of information that I'm trying to grab.

    var datas = new List<HourData>();
    HttpResponseMessage response = await client.GetAsync(_url);
    if (response.IsSuccessStatusCode)
    {
      var content = await response.Content.ReadAsStringAsync();

      JObject obj = JObject.Parse(content);

      var token = obj.SelectToken("data.weather");
      var tokenHours = (JArray)token[0].SelectToken("hourly");

      foreach (var tk in tokenHours)
      {
        var json = JsonConvert.SerializeObject(tk);
        datas.Add(JsonConvert.DeserializeObject<HourData>(json));
      }
    }

  public class HourData
  {
    public string weatherDesc { get; set; }
    public string time { get; set; }
    public string tempF { get; set; }
    public string Summary { get; set; }
    public string Icon { get; set; }
    public string PrecipIntensity { get; set; }
    public string PrecipProbability { get; set; }
    public string Temperature { get; set; }
    public string ApparentTemperature { get; set; }
    public string DewPoint { get; set; }
    public string Humidity { get; set; }
    public string Pressure { get; set; }
    public string windSpeed { get; set; }
    public string windGust { get; set; }
    public string windBearing { get; set; }
    public string cloudCover { get; set; }
    public string uvIndex { get; set; }
    public string visibility { get; set; }
    public string windspeedMiles { get; set; }
  }

The json in question is like this:

{
    "data": {
        "request": [
            {
                "type": "LatLon",
                "query": "Lat 33.41 and Lon -86.94"
            }
        ],
        "nearest_area": [
            {
                "areaName": [
                    {
                        "value": "Bessemer Homestead"
                    }
                ],
                "country": [
                    {
                        "value": "United States of America"
                    }
                ],
                "region": [
                    {
                        "value": "Alabama"
                    }
                ],
                "latitude": "33.404",
                "longitude": "-86.939",
                "population": "0",
                "weatherUrl": [
                    {
                        "value": "http://api-cdn.worldweatheronline.com/v2/weather.aspx?q=33.4063059,-86.9385553"
                    }
                ]
            }
        ],
        "weather": [
            {
                "date": "2019-04-20",
                "astronomy": [
                    {
                        "sunrise": "06:12 AM",
                        "sunset": "07:22 PM",
                        "moonrise": "08:54 PM",
                        "moonset": "07:15 AM",
                        "moon_phase": "Waxing Gibbous",
                        "moon_illumination": "88"
                    }
                ],
                "maxtempC": "16",
                "maxtempF": "61",
                "mintempC": "7",
                "mintempF": "45",
                "totalSnow_cm": "0.0",
                "sunHour": "9.1",
                "uvIndex": "3",
                "hourly": [
                    {
                        "time": "0",
                        "tempC": "7",
                        "tempF": "44",
                        "windspeedMiles": "11",
                        "windspeedKmph": "17",
                        "winddirDegree": "278",
                        "winddir16Point": "W",
                        "weatherCode": "122",
                        "weatherIconUrl": [
                            {
                                "value": "http://cdn.worldweatheronline.net/images/wsymbols01_png_64/wsymbol_0004_black_low_cloud.png"
                            }
                        ],
                        "weatherDesc": [
                            {
                                "value": "Overcast"
                            }
                        ],
                        "precipMM": "0.1",
                        "humidity": "84",
                        "visibility": "5",
                        "pressure": "1009",
                        "cloudcover": "100",
                        "HeatIndexC": "7",
                        "HeatIndexF": "44",
                        "DewPointC": "4",
                        "DewPointF": "40",
                        "WindChillC": "4",
                        "WindChillF": "39",
                        "WindGustMiles": "15",
                        "WindGustKmph": "24",
                        "FeelsLikeC": "4",
                        "FeelsLikeF": "39",
                        "uvIndex": "0"

I'm trying to get to this portion of the json:

                    "weatherDesc": [
                        {
                            "value": "Overcast"
                        }

When I add weatherDesc to HourData, I'm getting this exception:

Newtonsoft.Json.JsonReaderException: Error reading string. Unexpected token: StartArray. Path 'weatherDesc', line 1, position 280. at Newtonsoft.Json.JsonReader.ReadAsStringInternal() at Newtonsoft.Json.JsonTextReader.ReadAsString() at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.ReadForType(JsonReader reader, JsonContract contract, Boolean hasConverter) at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateObject(Object newObject, JsonReader reader, JsonObjectContract contract, JsonProperty member, String id) at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue) at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue) at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent) at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType) at Newtonsoft.Json.JsonConvert.DeserializeObject(String value, Type type, JsonSerializerSettings settings) at Newtonsoft.Json.JsonConvert.DeserializeObject[T](String value, JsonSerializerSettings settings) at Newtonsoft.Json.JsonConvert.DeserializeObject[T](String value) at SuburbanWebService.ddays.apis.DarkskyApiReader.d__6.MoveNext() in D:\Source\techguy\Suburban Test Projects\DarkSkyTest\DarkSkyTest\DarkskyApiReader.cs:line 151 One or more errors occurred.

Everything parses fine except the weatherDesc. I get the idea that it's not stepping in to that portion of the json, at least that is my understanding. How do I step in to the weatherDesc and pull the data in to my class?

Any help would be greatly appreciated!

2
You could create a class for WeatherDesc as it is an array and then use the newly created type in your HourData class public IEnumerable<WeatherDesc> weatherDesc { get; set; } - Vidmantas Blazevicius

2 Answers

2
votes

Create a class to hold the data for weatherDesc:

public class WeatherDesc 
{
     public string Value { get; set; }
}

Then use it in your HourData class:

public class HourData
{
    public IEnumerable<WeatherDesc> weatherDesc { get; set; }
    ...
}

As per the error, it is reading an array, hence why IEnumerable.

0
votes

The main issue lies in the fact that weatherDesc is actually an array rather than a singular string. You should be able to fix this by making the weatherDesc field a string[] rather than a string. If you wanted to flatten the singleton (collection that contains only 1 entry) array into just a string, you would have to deserialize the object yourself.