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

Asked

Viewed 274 times

3

I have no experience with JSON or web services consumption, but I am trying to consume an API that gives me weather data.

Here is the documentation of the API I’m trying to consume.

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

That’s right?

But as I know precisely the types of properties of the objects I’m receiving in JSON?

In the API I mentioned I found an example answer, 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 Paste Special > Paste the JSON classes, which generated 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, when 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 change the types of data in the properties of the classes I created. My question is, am I doing this the right way? Something is missing from the official API documentation, where they should report data types?

This kind of implementation in trial and error, performing tests and discovering the types of properties for sure should not be right.

1 answer

3


Yes, the way it is currently used is correct and you have the problem pointed out. If the property type on the server is changed you have to change the property of your model to the right type. There is a way to avoid this using the dynamic which 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 

it is noted that this approach has dynamic typification (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 just remembered that a better alternative might be to make your properties Nullable. For example instead of using int use int?, instead of float use float? and so on. That way if the property does not exist it takes the null value and the deserialization works smoothly.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.