Reputation: 7615
public class ZiptasticAPIResponse
{
[JsonPropertyName("country")]
public string country { get; set; }
[JsonPropertyName("state")]
public string DefaultState { get; set; }
[JsonPropertyName("city")]
public string DefaultCity { get; set; }
[JsonPropertyName("citiesList")]
public List<CitiesList> CitiesList { get; set; }
}
var url = _alternateURL + zip;
using (var request = new HttpRequestMessage(new HttpMethod("GET"), url))
{
var response = await httpClient.SendAsync(request);
Console.WriteLine("--------------------------");
var content = await response.Content.ReadAsStringAsync();
var ziptasticResponse = JsonConvert.DeserializeObject<ZiptasticAPIResponse>(content);
ziptasticResponse.CitiesList = new List<CitiesList>()
{
new CitiesList()
{
State=ziptasticResponse.DefaultCity,City=ziptasticResponse.DefaultCity
}
};
return ziptasticResponse.CitiesList;
I am getting null for DefaultCity and DefaultState but my country is 'US'
when I enter the url in my browser, I get the entire city, state
https://ziptasticapi.com/90210
What am I missing here?
Upvotes: 0
Views: 56
Reputation: 116980
Your problem is caused by the fact that you are mixing attributes and methods from different serializers. The attribute JsonPropertyName
is from System.Text.Json but you are using JsonConvert.DeserializeObject<T>()
from Json.NET to deserialize your JSON string. You need to use attributes and methods from the same serializer consistently.
If you want to deserialize using Json.NET, annotate your model with Newtonsoft.Json.JsonPropertyAttribute
instead of System.Text.Json.Serialization.JsonPropertyName
:
public class ZiptasticAPIResponse
{
[Newtonsoft.Json.JsonProperty("country")]
public string country { get; set; }
[Newtonsoft.Json.JsonProperty("state")]
public string DefaultState { get; set; }
[Newtonsoft.Json.JsonProperty("city")]
public string DefaultCity { get; set; }
[Newtonsoft.Json.JsonProperty("citiesList")]
public List<CitiesList> CitiesList { get; set; }
}
And the later
var ziptasticResponse = JsonConvert.DeserializeObject<ZiptasticAPIResponse>(content);
If you would prefer to use System.Text.Json
in .NET 5.0 you may use HttpClientJsonExtensions.GetFromJsonAsync
and leave ZiptasticAPIResponse
unchanged:
var url = _alternateURL + zip;
try
{
var ziptasticResponse = await httpClient.GetFromJsonAsync<ZiptasticAPIResponse>(url);
return ziptasticResponse;
}
catch (HttpRequestException ex) // Request failed.
{
// Check status code
var statusCode = ex.StatusCode;
Console.WriteLine(statusCode);
}
catch (JsonException) // Malformed JSON
{
Console.WriteLine("Invalid JSON.");
}
catch (NotSupportedException)
{
//https://learn.microsoft.com/en-us/aspnet/core/blazor/call-web-api?view=aspnetcore-5.0#handle-errors
Console.WriteLine("The content type is not application/json.");
}
// handle other exceptions or let them be handled at some higher level.
No matter which you choose, you might want to avoid mixing using Newtonsoft.Json.*
and using System.Text.Json.*
using statements in any given file. It's easy to make this mistake as the Newtonsoft and System.Text.Json attributes have very similar, and sometimes identical, names.
Demo fiddle for System.Text.Json here.
Upvotes: 1