0

From the website metcheck I am able to get a json file of the weather forecast. http://ws1.metcheck.com/ENGINE/v9_0/json.asp?lat=52.380&lon=0.060&Fc=Av

The file came back but I cannot read it to get out the info I need. I think I do not understand the relationship between metcheckData, forecastLocation and forecast:

{
   "metcheckData":{
      "forecastLocation":{
         "forecast":[
            {
               "temperature":"18",
               "dewpoint":"13",
               "rain":"0.0",
               "freezinglevel":"3049",
               "uvIndex":"1",
               "totalcloud":"65",
               "lowcloud":"55",
               "medcloud":"43",
               "highcloud":"11",
               "humidity":"79",
               "windspeed":"11",
               "meansealevelpressure":"1012.77",
               "windgustspeed":"17",
               "winddirection":"249",
               "windletter":"WSW",
               "icon":"PC",
               "iconName":"Partly Cloudy",
               "chanceofrain":"0",
               "chanceofsnow":"0",
               "dayOfWeek":"4",
               "weekday":"Wednesday",
               "sunrise":"6:02",
               "sunset":"18:09",
               "cumulusBaseHeight":"540",
               "stratusBaseHeight":"549",
               "dayOrNight":"N",
               "utcTime":"2019-07-31T19:00:00.00"
            },
            {
               "temperature":"17",
               "dewpoint":"13",
               "rain":"0.1",
               "freezinglevel":"3192",
               "uvIndex":"0",
               "totalcloud":"91",
               "lowcloud":"66",
               "medcloud":"39",
               "highcloud":"35",
               "humidity":"82",
               "windspeed":"11",
               "meansealevelpressure":"1013.29",
               "windgustspeed":"17",
               "winddirection":"245",
               "windletter":"WSW",
               "icon":"RO",
               "iconName":"Intermittent Rain",
               "chanceofrain":"47",
               "chanceofsnow":"0",
               "dayOfWeek":"4",
               "weekday":"Wednesday",
               "sunrise":"6:02",
               "sunset":"18:09",
               "cumulusBaseHeight":"512",
               "stratusBaseHeight":"520",
               "dayOrNight":"N",
               "utcTime":"2019-07-31T20:00:00.00"
            }
         ],
         "continent":"",
         "country":"",
         "location":"52.4/0.1",
         "latitude":52.4,
         "longitude":0.1,
         "timezone":0
      }
      // Many other similar array entries omitted
   },
   "feedCreation":"2019-07-31T20:26:10.00",
   "feedCreator":"Metcheck.com",
   "feedModel":"GHX5",
   "feedModelRun":"00Z",
   "feedModelRunInitialTime":"2019-07-31T00:00:00.00",
   "feedResolution":"0.01"
}

Using using Newtonsoft.Json; using Newtonsoft.Json.Linq;

I tried the following code to read out things like the temperature forecast for the specific hour.

 JObject jo = JObject.Parse(File.ReadAllText(@"C:\temp\Weather.json", Encoding.UTF8));
 Dictionary<string, List<string>> values =
            jo.SelectToken("forecast", true).ToObject<Dictionary<string, List<string>>>();

 foreach (var kv in values)
 {
     rchtxtbx_output.AppendText(kv.Value[0] + "\r");

and so on thinking kv.Value[0] will be the temperature and I will go round and get the temperature for each hour. Unfortunately that is not the case and I get errors at

Dictionary<string, List<string>> values =
                jo.SelectToken("forecast", true).ToObject<Dictionary<string, List<string>>>();

So some how the "forecast" is not correct. I also tried metcheckData.forecastLocation.forecast and then forecastLocation.forecast but all had errors.

Any ideas how I get the data out of json file and write to richtext box for each hour of forecast please.

dbc
  • 104,963
  • 20
  • 228
  • 340
user3884423
  • 556
  • 1
  • 5
  • 20
  • 1
    I cleaned up the formatting of your JSON using https://jsonformatter.curiousconcept.com/. Feel free to revert the changes if I got anything wring. – dbc Jul 31 '19 at 19:35

3 Answers3

2

You want to navigate to the token you want via its parent tokens. Then grab the token's child list.

JObject jo = JObject.Parse(File.ReadAllText(@"C:\temp\Weather.json", Encoding.UTF8));

// navigate to the token via its parents
List<JToken> items = jo.SelectToken("metcheckData", true).SelectToken("forecastLocation", true).SelectToken("forecast", true).Children().ToList();

foreach (JToken token in items)    
{
    string temperature = token["temperature"].Value<string>();
    string dewpoint = token["dewpoint"].Value<string>();
    // etc...
}
quaabaam
  • 1,808
  • 1
  • 7
  • 15
1

Why not to create a mapping class and parse JSON to this object. After you did that you can go through all properties and select everything you need.

var data = JsonConvert.DeserializeObject<Rootobject>(File.ReadAllText(@"C:\temp\Weather.json", Encoding.UTF8));

public class Rootobject
{
    public Metcheckdata metcheckData { get; set; }
    public DateTime feedCreation { get; set; }
    public string feedCreator { get; set; }
    public string feedModel { get; set; }
    public string feedModelRun { get; set; }
    public DateTime feedModelRunInitialTime { get; set; }
    public string feedResolution { get; set; }
}

public class Metcheckdata
{
    public Forecastlocation forecastLocation { get; set; }
}

public class Forecastlocation
{
    public Forecast[] forecast { get; set; }
    public string continent { get; set; }
    public string country { get; set; }
    public string location { get; set; }
    public float latitude { get; set; }
    public float longitude { get; set; }
    public int timezone { get; set; }
}

public class Forecast
{
    public string temperature { get; set; }
    public string dewpoint { get; set; }
    public string rain { get; set; }
    public string freezinglevel { get; set; }
    public string uvIndex { get; set; }
    public string totalcloud { get; set; }
    public string lowcloud { get; set; }
    public string medcloud { get; set; }
    public string highcloud { get; set; }
    public string humidity { get; set; }
    public string windspeed { get; set; }
    public string meansealevelpressure { get; set; }
    public string windgustspeed { get; set; }
    public string winddirection { get; set; }
    public string windletter { get; set; }
    public string icon { get; set; }
    public string iconName { get; set; }
    public string chanceofrain { get; set; }
    public string chanceofsnow { get; set; }
    public string dayOfWeek { get; set; }
    public string weekday { get; set; }
    public string sunrise { get; set; }
    public string sunset { get; set; }
    public string cumulusBaseHeight { get; set; }
    public string stratusBaseHeight { get; set; }
    public string dayOrNight { get; set; }
    public DateTime utcTime { get; set; }
}
SouXin
  • 1,565
  • 11
  • 17
1

If you take the json from the link and ignorre the forecast part, this what you get:

{
    "metcheckData": {
        "forecastLocation": {
            "forecast": [],
            "continent": "",
            "country": "",
            "location": "52.4/0.1",
            "latitude": 52.4,
            "longitude": 0.1,
            "timezone": 0
        }
    },
    "feedCreation": "2019-07-31T20:17:52.00",
    "feedCreator": "Metcheck.com",
    "feedModel": "GHX5",
    "feedModelRun": "00Z",
    "feedModelRunInitialTime": "2019-07-31T00:00:00.00",
    "feedResolution": "0.01"
}

From this, it becomes more obvious (to me), that metacheckData and forecastLocation both are objects, and the forecast array is a property of forecastLocation.

What I would do, is using dynamics. Check this and this post

So it might become something like this (not tested):

var data = JsonConvert.DeserializeObject<dynamic>(rawJson);
var rawForecasts = data.metcheckData.forecastLocation.forecast;
terle
  • 86
  • 10