When consuming an API that returns me serialized data in JSON, how do I know the data types of the properties?

3

I have no experience with JSON or web services, but I'm trying to consume an API that returns me weather data.

Here is the documentation of the API I am trying to consume.

This API returns me serialized data in JSON. As I read about JSON, the best way to access this data after downloading them would be to de-serialize them to an object of a class with properties identical to the properties of the object returned by the web service.

Is that right?

But how do I know precisely the object properties types I'm getting in JSON?

In the API I mentioned I found an example response, this one:

{"coord":
{"lon":145.77,"lat":-16.92},
"weather":[{"id":803,"main":"Clouds","description":"broken clouds","icon":"04n"}],
"base":"cmc stations",
"main":{"temp":293.25,"pressure":1019,"humidity":83,"temp_min":289.82,"temp_max":295.37},
"wind":{"speed":5.1,"deg":150},
"clouds":{"all":75},
"rain":{"3h":3},
"dt":1435658272,
"sys":{"type":1,"id":8166,"message":0.0166,"country":"AU","sunrise":1435610796,"sunset":1435650870},
"id":2172797,
"name":"Cairns",
"cod":200}

What I did was copy this template, and paste it into Visual Studio using the Paste Special > Paste the JSON classes, which generated me these classes:

        public class Rootobject
        {
            public Coord coord { get; set; }
            public Weather[] weather { get; set; }
            public string _base { get; set; }
            public Main main { get; set; }
            public Wind wind { get; set; }
            public Clouds clouds { get; set; }
            public Rain rain { get; set; }
            public int dt { get; set; }
            public Sys sys { get; set; }
            public int id { get; set; }
            public string name { get; set; }
            public int cod { get; set; }
        }

        public class Coord
        {
            public float lon { get; set; }
            public float lat { get; set; }
        }

        public class Main
        {
            public float temp { get; set; }
            public int pressure { get; set; }
            public int humidity { get; set; }
            public float temp_min { get; set; }
            public float temp_max { get; set; }
        }

        public class Wind
        {
            public float speed { get; set; }
            public int deg { get; set; }
        }

        public class Clouds
        {
            public int all { get; set; }
        }

        public class Rain
        {
            public int _3h { get; set; }
        }

        public class Sys
        {
            public int type { get; set; }
            public int id { get; set; }
            public float message { 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; }
        }
The problem here is that when I download JSON via HttpClient, trying to de-serialize it, I get some type errors, such as trying to store floating-point data in float-type properties. My code:

string json = await client.GetStringAsync("weather?q=London,uk&appid=010101010101010101101");
Rootobject currentWeather = new Rootobject();
currentWeather = JsonConvert.DeserializeObject<Rootobject>(json);
MessageBox.Show(currentWeather.name);

I understand that in this case I could simply go about changing the data types in the properties of the classes I created. My question is, am I doing this procedure the right way? Is there anything missing from the official API documentation, where should I enter data types?

This type of implementation in trial and error, testing and discovering property types should certainly not be right.

    
asked by anonymous 14.10.2016 / 03:24

1 answer

3

Yes, the way you are currently using it is correct and has the problem you have pointed out. If the property type on the server is changed you have to change the ownership of your model to the right type. There is a way to avoid this by using dynamic that is available from C# 4.0

var converter = new ExpandoObjectConverter(); 
dynamic obj = JsonConvert.DeserializeObject(json, converter); 
//agora pode aceder as propriedades de obj 
var propriedade = obj.coord.lon 

Note that this approach has dynamic typing (this means that it has no help from the compiler to check the existing properties etc.) and is usually not encouraged for this very reason.

I now remembered that a better alternative might be to make their properties Nullable . For example instead of using int use int? , instead of float use float? and out there. That way if the property does not exist it takes null value and deserialization works without problems.

    
14.10.2016 / 10:49