I’m currently writing a c# wrapper library for an external REST API (which I have no control over), which returns JSON.
To deserializing the following JSON
{
"countries": {
"2": {
"name": "Albania",
"isoCode": "AL",
"dialCode": "+355"
},
"3": {
"name": "Algeria",
"isoCode": "DZ",
"dialCode": "+213"
},
"4": {
"name": "American Samoa",
"isoCode": "AS",
"dialCode": "+1684"
}
}
}
I have a method GetCountries in my library which does the following:
public List<Country> GetCountries()
{
string endpointUrl = GenerateEndPointUri(...)
var countries = IssueApiGETRequest<CountriesWrapper>(endpointUrl);
return countries.Countries.Select(x =>
{
x.Value.Id = x.Key;
return x.Value;
}).ToList();
}
The IssueAPIGetRequest look something like this:
private T IssueApiGETRequest<T>(string endPointUrl)
{
using (var handler = new HttpClientHandler())
{
handler.Credentials = ...;
using (HttpClient client = new HttpClient(handler))
{
var response = client.GetAsync(endPointUrl).Result;
if (response.IsSuccessStatusCode)
{
string json = response.Content.ReadAsStringAsync().Result;
var result = JsonConvert.DeserializeObject<T>(json);
return result;
}
else
{
switch (response.StatusCode)
{
case HttpStatusCode.BadRequest:
throw new InvalidParameterException("Invalid parameters");
}
throw new Exception("Unable to process request");
}
}
}
}
This allows me to define a generic method for all the GET endpoints on the external API and have them serialized into my own defined types.
Then finally, I have these Class entities defined:
[JsonObject(MemberSerialization = MemberSerialization.OptIn)]
internal class CountriesWrapper
{
[JsonProperty(PropertyName = "countries")]
public IDictionary<int, Country> Countries { get; set; }
}
[JsonObject(MemberSerialization = MemberSerialization.OptIn)]
public class Country
{
public int Id { get; set; }
[JsonProperty(PropertyName = "name")]
public string Name { get; set; }
[JsonProperty(PropertyName = "isoCode")]
public string IsoCode { get; set; }
[JsonProperty(PropertyName = "dialCode")]
public string DialCode { get; set; }
}
I’m not very happy with the GetCountries method, which has to reiterate over the Dictionary that is returned from the deserialization, and having the CountriesWrapper class.
QUESTION: I would like to know if I’m missing a trick or if someone can suggest a cleaner way of laying this out. Whilst keeping a generic method of issuing GET requests to the external API.
This can be done with a JsonConverter similar like this answer
I think It’s very the strange the json, anyway I implemented the Converter that can read that sort of json. I don’t think it’s well implemented but you can improve it
And the country class, that it’s the same just de BuildCountry Method