C# - Курсы валют НБУ в Json формате

В этой статье мы создадим программу, которая загружает курсы валют с сайта НБУ, после чего эти курсы выводит на экран в удобном для восприятия виде.

Если вы думаете, при чем тут курсы валют, я ж не банкир? Зачем мне это не нужно? Вы ошибаетесь - если вам не нужны курсы валют, то технологии, рассмотренные здесь вам обязательно пригодятся в будущем.

Создайте проект

  1. Нажмите кнопку Create a new project.
  2. Шаг Create new project:

    • Выбираем фильтр:

      • Язык программирования: C#
      • Платформа: Windows
      • Тип проекта: Desktop
    • Выбираем Windows Forms App (Net. Framework) - нажимаем Next
  3. Шаг Configure your project:
    Название проекта: CurrencyFormApp
    Название решения: Currency.
    Framework: Оставляем по умолчанию, на данном этапе не важно какая версия Net. Framework
  4. Нажимаем Create

Открылось главное окно Visual Studio и пустая форма, которую вы сейчас заполните.

Примечание

Для упрощения поиска нужного элемента в Панели элеметов воспользуйтесь поиском в верху панели.

Добавление элементов управления на форму

Добавьте следующие элементы управления и установите их свойства:

  • Button (Кнопка):

    • Name: buttonDownload
    • Text: "Загрузить"
    • Anchor: Top, Right
  • TextBox (Текстовое поле)

    • Name: textBoxFilter
    • Anchor: Top, Left, Right
  • Label (Надпись)

    • Name: lblFilter
    • Text: Фильтр
    • Anchor: Top, Left
  • DateTimePicker

    • Name: dtpCurrencyDate
    • Anchor: Top, Left
  • ListView

    • Name: listViewCurrates
    • Anchor: Top, Bottom, Left, Right
    • View: Details
    • Columns:

      • Name: N Code
      • Name: Text
      • Name: Rate
      • Name: C Code

Подготовка проекта для работы с данными в формате Json

Для того, чтоб представлять себе, в каком виде курсы валют возвращаются сервером, следует перейти по ссылке:

Для того, чтоб работать с данными в формате Json, следует воспользоваться менеджером пакетов NuGet для установки библиотеки Newtonsoft.Json.

  1. Откройте Обозреватель решений
  2. Правой кнопкой выберите проект, для которого следует добавить пакет Newtonsoft.Json
  3. В открывшемся меню выберите Управление пакетами NuGet
  4. Выберите Newtonsoft.Json и нажмите кнопку Установить

В добавок, каждая валюта, должна быть представлена в виде типа, будем его называть CurrencyRate. Для его описания создайте класс:

  1. Откройте Обозреватель решений
  2. Правой кнопкой мыши выберите проект, внутри которго следует создать класс в данном случае это CurratesFormApp
  3. В открывшемся меню выберите Добавить - Класс
  4. Укажите имя класса CurrencyRate и нажмите кнопку Добавить
  5. Приведите класс к следующему виду:
[JsonObject(MemberSerialization = MemberSerialization.OptIn)]
public class CurrencyRate
{
	//"r030":36,"txt":"Австралійський долар","rate":21.6395,"cc":"AUD","exchangedate":"17.02.2021"
	
	[JsonProperty(PropertyName = "r030")]
	public int r030 { get; set; }
	
	[JsonProperty(PropertyName = "txt")]
	public string txt { get; set; }
	
	[JsonProperty(PropertyName = "rate")]
	public float rate { get; set; }
	
	[JsonProperty(PropertyName = "cc")]
	public string cc { get; set; }
	
	[JsonProperty(PropertyName = "exchangedate")]
	public string exchangedate { get; set; }

	public string[] ToStringArray()
	{
		string[] arr = new String[] { r030.ToString(), txt, rate.ToString(), cc };
		return arr;
	}
}

Обработчик события нажатия кнопки Загрузить

Добавьте обработчик события нажатия кнопки buttonDownload:

private void buttonDownload_Click(object sender, EventArgs e)
{
	string date = dateTimePickerCurrencyDate.Value.ToString("yyyyMMdd");
	string URI = $"https://bank.gov.ua/NBUStatService/v1/statdirectory/exchange?date={date}&json";
	string webResponseString; // Здесь храниться Json, полученный с сервера

	// Создаем Веб запрос для URL.
	WebRequest request = WebRequest.Create(URI);
	request.Method = WebRequestMethods.Http.Get;

	//читаем ответ с сервера
	using (WebResponse response = request.GetResponse())
	{
		// тип Stream предоставляет набор низкоуроневых средств 
		// для представления и взаимодействия с потоком данных.
		using (Stream dataStream = response.GetResponseStream())
		{
			// именно этот тип позволит нам прочитать все данные полученные от сервера, 
			// выполнив всего-лишь один метод ReadToEnd()
			StreamReader streamRdr = new StreamReader(dataStream);
			webResponseString = streamRdr.ReadToEnd();
		}
	};

	// Список объектов типа CurrencyRate
	List<CurrencyRate> currRates = JsonConvert.DeserializeObject<List<CurrencyRate>>(webResponseString);
	
	// Очищаем listViewCurrates от ранее загруженных элементов
	listViewCurrates.Items.Clear();

	foreach (var item in currRates)
	{
		listViewCurrates.Items.Add(new ListViewItem(item.ToStringArray()));
	}
}

Ну вот. Программа промежуточно уже имеет рабочее состояние:

Теперь нужно привести программу в надлежащий вид.

Обработчик buttonDownload_Click можно разбить на три логические части

  1. Загрузка курсов валют из Интернет
  2. Парсинг Json ответа от сервера.
  3. Вывод полученных элементов на экран

Данный метод делает три задачи, что противоречит основополагающему принципу ООП: SRP (Single Responcibility Principle - Принцип единственной ответственности). Поэтому данный метод, следует переписать:

  • Код, относящийся к этапу загрузки курсов валют нужно вынести в метод GetWebContent
  • Код, отвечающий за вывод курсов валют на экран, вынести в метод FillCurrencyList.

В итоге, мы получаем три метода buttonDownload_Click(), который в процессе выполнения вызывает методы GetWebContent() и FillCurrencyList():

private void buttonDownload_Click(object sender, EventArgs e)
{
	string date = dateTimePickerCurrencyDate.Value.ToString("yyyyMMdd");
	string URI = $"https://bank.gov.ua/NBUStatService/v1/statdirectory/exchange?date={date}&json";

	string webResponseString = GetWebContent(URI);

	// Список объектов типа CurrencyRate
	List<CurrencyRate> currRates = JsonConvert.DeserializeObject<List<CurrencyRate>>(webResponseString);

	FillCurrencyList(currRates);
}

string GetWebContent(string UriString)
{
	string webResponseString;

	// Create a request for the URL.
	WebRequest request = WebRequest.Create(UriString);
	request.Method = WebRequestMethods.Http.Get;
	//request.Credentials = CredentialCache.DefaultCredentials;

	using (WebResponse response = request.GetResponse())
	{
		using (Stream dataStream = response.GetResponseStream())
		{
			StreamReader streamRdr = new StreamReader(dataStream);
			webResponseString = streamRdr.ReadToEnd();
		}
	};

	return webResponseString;
}

void FillCurrencyList(List<CurrencyRate> currRates)
{
	// Очищаем listViewCurrates от ранее загруженных элементов
	listViewCurrates.Items.Clear();

	foreach (var item in currRates)
	{
           // фильтруем список выводимых элементов
           if (item.txt.ToLower().Contains(textBoxFilter.Text.ToLower()))
           {
               listViewCurrates.Items.Add(new ListViewItem(item.ToStringArray()));
           }
	}
}

Отдельно хочется остановиться на конструкции следующего вида:

using (WebResponse response = request.GetResponse())
{
    ...
}

В данном контексте, using это оператор, который позволяет не заморачиваться об освобождении ресурсов, и закрытии файловых дескрипторов. Освобождение ресурсов средой выполянется средой CLR автоматически, путем вызова метода Dispose(), после того, как работа программы вышла за пределы области видимости данного оператора (область видимости задается фигурными скобками).

Для возможности использования оператора using, объект данного типа должен реализовывать интерфейс IDisposable. Вопрос использования интерфейсов будет рассмотрен в других материалах.

Создание библиотеки классов

Предположим, что созданные вами методы будут нужны не только в этой программе, но и в других решениях, где нужно будет выполнять схожие операции.  Для того, чтоб избежать дублирования одного и того-же кода в разных проектах, целесообразно вынести код в отдельную библиотеку, которую, в свою очередь, подключить к решению. Данный подход позволит вам придерживаться основополагающего принципа ООП: DRY - Don't Repeat Yourself - Не повторяйся.

Например, данная программа создавалась как Windows Forms Application, но в рамках этого же решения мы создадим консольное приложение, которе выводит список курсов валют в консоль.

Для добавления библиотеки:

  1. Откройте Обозреватель решений
  2. Правой кнопкой мыши выберите решение, в данном случае это Currency
  3. Шаг Create new project:

    • Выберите фильтр:

      • Язык программирования: C#
      • Платформа: Windows
      • Тип проекта: Desktop
    • Выберите Библиотека классов (Net. Framework) - нажмите Next
  4. Шаг Configure your project:
    Название проекта: MyLib
  5. Обратите внимание, что данный мастер не предлагает выбрать название решения - проект будет добавлен в текущее решение
  6. Framework: Оставляем по умолчанию
  7. Нажимаем Create

Для перемещения метода GetWebContent проделайте следующие действия:

  1. Переименуйте класс Class1 в Web - этот класс будет хранить созданные вами методы, относящиеся к работе с Интернет.
  2. Скопируйте метод GetWebContent из класса Form1 в только созданный вами класс Web

Примечание

Для переименования классов используйте мастер переименования, который переименует не только сам класс, но и файл в которм он находится, и все ссылки на него в вашей программе.

Для перемещения класса CurrencyRate проделайте следующие действия:

  1. Откройте Обозреватель решений
  2. Разверните проект CurrencyFormApp
  3. Выберите правой кнопкой мыши файл CurrencyRate.cs - Копировать
  4. Выберите правой кнопкой мыши проект MyLib - Вставить
  5. В только что скопированном файле CurrencyRate.cs переименуйте пространство имен CurrencyFormApp в MyLib

Создание консольного приложения

Теперь давайте создадим консольное приложение

  1. Откройте Обозреватель решений
  2. Правой кнопкой мыши выберите решение, в данном случае это Currency
  3. Нажмите кнопку Create a new project.
  4. Шаг Create new project:

    • Выберите фильтр:

      • Язык программирования: C#
      • Платформа: Windows
      • Тип проекта: Консоль
    • Выберите Консольное приложение (Net. Framework) - нажмите Next
  5. Шаг Configure your project:
    Название проекта: CurrencyConsoleApp
  6. Обратите внимание, что данный мастер не предлагает выбрать название решения - проект будет добавлен в текущее решение
  7. Framework: Оставляем по умолчанию
  8. Нажимаем Create
  9. Добавьте ссылку на библиотеку MyLib:

    • Открыть: Ссылки - Добавить ссылку - Проекты
    • Установить чекбокс MyLib, нажать OK

Файл program.cs сделайте следующего вида:

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using MyLib;

namespace CurrencyApp
{
    class Program
    {
        static void Main(string[] args)
        {
            string URI = "https://bank.gov.ua/NBUStatService/v1/statdirectory/exchange?json";

            string jsonFromServer = Web.GetWebContent(URI);
            JsonTextReader reader = new JsonTextReader(new StringReader(jsonFromServer));

            List<CurrencyRate> currRates = JsonConvert.DeserializeObject<List<CurrencyRate>>(jsonFromServer);

            foreach (var item in currRates)
            {
                Console.WriteLine($" { item.cc } { item.rate } { item.exchangedate } ");
            }
            
            _ = Console.ReadLine();

        }
    }
}

Если у вас решение содержит несколько исполняемых проектов, изменить запускаемый проект можно в выпадающем списке как на рисунке ниже

Вывод программы

Както так. Если у вас есть вопросы, или замечания - пишите.

Код проекта доступен на GitHub.

Добавить комментарий

Filtered HTML

  • Адреса страниц и электронной почты автоматически преобразуются в ссылки.
  • Разрешённые HTML-теги: <a> <s> <u> <em> <strong> <cite> <blockquote> <code> <ul> <ol> <li> <dl> <dt> <hr> <dd> <sub> <sup>
  • Строки и параграфы переносятся автоматически.

Plain text

  • HTML-теги не обрабатываются и показываются как обычный текст
  • Строки и параграфы переносятся автоматически.
CAPTCHA
Защита от СПАМ ботов. Подтвердите, пожалуйста, что вы человек.
7 + 6 =
Решите эту простую математическую задачу и введите результат. Например, для 1+3, введите 4.