问题
I need to write the titles of the countries from VK API to a list from the following link.
I have written some code:
public class GettingCountry
{
public async Task<string> FetchAsync(string url)
{
string jsonString;
using (var httpClient = new System.Net.Http.HttpClient())
{
var stream = await httpClient.GetStreamAsync(url);
StreamReader reader = new StreamReader(stream);
jsonString = reader.ReadToEnd();
}
var readJson = JObject.Parse(jsonString);
string countryName = readJson["response"]["items"].ToString();
var deserialized = JsonConvert.DeserializeObject<RootObject>(jsonString);
return jsonString;
}
}
public class Item
{
public int id { get; set; }
public string title { get; set; }
}
public class Response
{
public int count { get; set; }
public List<Item> items { get; set; }
}
public class RootObject
{
public Response response { get; set; }
}
}
I put a breakpoint and got in string countryName
only this:
回答1:
As you can see the VK API returns you an array of objects. Your jsonString contains full response string. Now, jsonString["response"]["items"] contains an array of items.
First you need to parse the array and then parse each item, like this:
var readJson = JObject.Parse(jsonString);
JArray countries = JArray.Parse(readJson["response"]["items"]);
var Response listOfCountries = new Response();
foreach (var country in countries) {
Item currentCountry = new Item();
currentCountry.id = country.id;
currentCountry.title = country.title;
listOfCountries.items.Add(currentCountry);
}
listOfCountries.count = listOfCountries.items.Count;
From the code perspective, I would recommend giving proper names to variables, classes, and types to improve code readability and cleanliness. On top of it, I don't really see a point in having a separate Response class. For example, you could rename your Item class and call it Country. All you need to have is a list of countries then. Also, because you're using async method, you want to do the processing of the return within your using for the HttpClient - if you don't the client might be disposed too soon and you might start hitting very weird bugs. Like this:
public class VkCountry
{
public int Id { get; }
public string Title { get; }
public VkCountry(int countryId, string countryTitle) {
this.Id = countryId;
this.Title = countryTitle;
}
}
public async Task<List<VkCountry>> FetchAsync(string url)
{
string jsonString;
using (var httpClient = new System.Net.Http.HttpClient())
{
var stream = await httpClient.GetStreamAsync(url);
StreamReader reader = new StreamReader(stream);
jsonString = reader.ReadToEnd();
var listOfCountries = new List<VkCountry>();
var responseCountries = JArray.Parse(JObject.Parse(jsonString)["response"]["items"].ToString());
foreach (var countryInResponse in responseCountries) {
var vkCountry = new VkCountry((int)countryInResponse["id"], (string)countryInResponse["title"]);
listOfCountries.Add(vkCountry);
}
return listOfCountries;
}
}
You might notice that I've made VkContry implementation immutable, the properties are read-only and can be set using the constructor only. I'd recommend using immutable objects when you are consuming relatively static third-party APIs (list of countries is definitely static, unless some kind of application logic will require you to update the name of the country). Obviously, you might want to add nullability checks and different validations.
来源:https://stackoverflow.com/questions/42881688/writing-countries-to-a-list-from-vk-api