다음을 통해 공유


C# - JSON Currency Converter

Overview

This is a currency converter application, that gets rates from the online daily updated JSON file at http://www.floatrates.com/daily/eur.json

The raw JSON data is deserialized to a Dictionary(Of String, currencyDetails). The Dictionary stores all of the details about each currency, including an Overridden ToString method which returns the three character currency code, a hyphen, and the official currency name. Two Arrays derived from the Dictionary serve as DataSources for the From and To ComboBoxes. The ComboBoxes display the currencies and are sorted ASC. 

In Form_Load after the JSON is deserialized, a Table Class containing a Shared Array is called to create the Array used to store all of the currency rates used by the converter. This is also arranged ASC, so the correct Array indices will be the From and To ComboBox SelectedIndices, and converting any of 148 currencies to any other of the 148 currencies is easily achieved.

This example uses just one Class for the currencyDetails obtained from the JSON, and another Class to host the Shared Array. Other than setting up the DataSources, creating the Table, and converting the currencies, there's just several GUI handlers for ensuring the results Label is kept up to date, and there's some painting in the Form_Paint event.

SystemColors are used in the Form to create a contrasting appearance, which should work well, however, your current color scheme is set up.

The Code

The Form

The code here is annotated, explaining step by step...



      using Newtonsoft.Json;
      using System;
      using System.Collections.Generic;
      using System.ComponentModel;
      using System.Data;
      using System.Drawing;
      using System.Linq;
      using System.Net;
      using System.Text;
      using System.Threading.Tasks;
      using System.Windows.Forms;
   
      namespace JSON_Currency_Converter_cs
      {  
                    public partial  class Form1 : Form  
                    {      
                        public Form1()  
                        {      
                            InitializeComponent();      
                            this      .Paint += Form1_Paint;      
                            nudAmount.ValueChanged += inputs_ValuesChanged;      
                            cboFrom.SelectedIndexChanged += inputs_ValuesChanged;      
                            cboTo.SelectedIndexChanged += inputs_ValuesChanged;      
                            nudAmount.Leave += inputs_ValuesChanged;      
                            cboFrom.Leave += inputs_ValuesChanged;      
                            cboTo.Leave += inputs_ValuesChanged;      
                        }      
   
                        private void  Form1_Load(object  sender, EventArgs e)  
                        {      
                            WebClient client =       new  WebClient();  
                            string rawResponseString = client.DownloadString("http://www.floatrates.com/daily/eur.json");  
   
                            //This is the Dictionary that, along with the table Array,       
                            //creates the core of this application.      
                            //The base currency for the rates obtained from the JSON is the Euro      
                            Dictionary<      string      , currencyDetails> jsonResulttodict = JsonConvert.DeserializeObject<Dictionary<      string      , currencyDetails>>(rawResponseString);      
                            jsonResulttodict.Add(      "eur"      ,       new  currencyDetails("EUR", "Euro",  "1", jsonResulttodict["gbp"].dateString, "1"));  
   
                            //These are all used simply for creation of the 2D table Array      
                            //that is used throughout this application      
                            string      [] codes = jsonResulttodict.Select((kvp) => kvp.Value.code).ToArray();      
                            string      [] tempCodes = (      string      [])codes.Clone();      
                            decimal      [] rates = jsonResulttodict.Select((kvp) => kvp.Value.rate).ToArray();      
                            decimal      [] inverse = jsonResulttodict.Select((kvp) => kvp.Value.inverseRate).ToArray();      
                            Array.Sort(codes, rates);      
                            Array.Sort(tempCodes, inverse);      
   
                            Table.createArray(codes, rates, inverse);      
   
                            //These have two separately created Arrays. The Arrays are identical      
                            //but using one single Array for both ComboBoxes wouldn't allow      
                            //the ComboBoxes to work independently of each other...      
                            cboFrom.DataSource = jsonResulttodict.Select((kvp) => kvp.Value).OrderBy((cd) => cd.ToString()).ToArray();      
                            cboTo.DataSource = jsonResulttodict.Select((kvp) => kvp.Value).OrderBy((cd) => cd.ToString()).ToArray();      
   
                            //To ensure conversion takes place ASAP      
                            foreach (Control ctrl in this.Controls)  
                            {      
                                if (ctrl == nudAmount)  
                                {      
                                    continue      ;      
                                }      
                                ctrl.Click += ctrls_Click;      
                            }      
                            this      .Click += ctrls_Click;      
   
                        }      
   
                        private void  ctrls_Click(object  sender, EventArgs e)  
                        {      
                            if (sender == this)  
                            {      
                                lblResults.Select();      
                            }      
                        ((Control)sender).Select();      
                        }      
   
                        private void  inputs_ValuesChanged(object sender, EventArgs e)  
                        {      
                            if (cboFrom.SelectedIndex < 0 || cboTo.SelectedIndex < 0 || nudAmount.Value == 0M)  
                            {      
                                lblResults.Text =       ""      ;      
                                return      ;      
                            }      
                            lblResults.Text = nudAmount.Value.ToString() +       " " + cboFrom.Text.Substring(0, 3) + Environment.NewLine +  
                                "equals... " + Environment.NewLine + (Table.getValueAt(cboFrom.SelectedIndex, cboTo.SelectedIndex) * nudAmount.Value).ToString() +   
                                " " + cboTo.Text.Substring(0, 3) + Environment.NewLine + Environment.NewLine + "Currency rates updated - "  +   
                                ((currencyDetails)cboFrom.SelectedItem).dateString;      
                        }      
   
                        //This just paints some contrasting borders, in       
                        //keeping with the systemcolors contrasting theme      
                        private void  Form1_Paint(object  sender, PaintEventArgs e)  
                        {      
                            ControlPaint.DrawBorder(e.Graphics,       new  Rectangle(nudAmount.Left - 2, nudAmount.Top - 2, nudAmount.Width + 4, nudAmount.Height + 4), SystemColors.Control, ButtonBorderStyle.Solid);  
                            ControlPaint.DrawBorder(e.Graphics,       new  Rectangle(cboFrom.Left - 2, cboFrom.Top - 2, cboFrom.Width + 4, cboFrom.Height + 4), SystemColors.Control, ButtonBorderStyle.Solid);  
                            ControlPaint.DrawBorder(e.Graphics,       new  Rectangle(cboTo.Left - 2, cboTo.Top - 2, cboTo.Width + 4, cboTo.Height + 4), SystemColors.Control, ButtonBorderStyle.Solid);  
                            ControlPaint.DrawBorder(e.Graphics,       new  Rectangle(lblResults.Left - 3, lblResults.Top - 3, lblResults.Width + 6, lblResults.Height + 6), SystemColors.Control, ButtonBorderStyle.Solid);  
                        }      
   
   
                    }      
      }  

The Table Class



      using System;
      using System.Collections.Generic;
      using System.Linq;
      using System.Text;
      using System.Threading.Tasks;
   
      namespace JSON_Currency_Converter_cs
      {  
                    public class  Table  
                    {      
                        private static  decimal[][] values;  
   
                        public static  void createArray(string[] codes, decimal[] rates, decimal[] inverse)  
                        {      
                            //When complete, each cell of the table contains the value      
                            //for one 'From' unit's value in 'To' units      
                            values =       new  decimal[codes.GetUpperBound(0) + 1][];  
                            for (int x = 0; x < codes.Length; x++)  
                            {      
                                values[x] =       new  decimal[codes.GetUpperBound(0) + 1];  
                                values[x][0] = rates[x];      
                                values[0][x] = inverse[x];      
                                values[x][x] = 1M;      
                            }      
                            for (int c = 1; c < codes.Length; c++)  
                            {      
                                for (int r = 1; r < codes.Length; r++)  
                                {      
                                    values[r][c] = (      decimal      )(values[0][c] / values[0][r]);      
                                }      
                            }      
                        }      
   
                        public static  decimal getValueAt(int c, int r)  
                        {      
                            return values[r][c];  
                        }      
   
                    }      
   
      }  

The currencyDetails Class



      using System;
      using System.Collections.Generic;
      using System.Linq;
      using System.Text;
      using System.Threading.Tasks;
   
      namespace JSON_Currency_Converter_cs
      {  
                    public class  currencyDetails  
                    {      
                        public string  code { get; set; }  
                        public string  name { get; set; }  
                        public decimal  rate { get; set; }  
                        public string  dateString { get; set; }  
                        public decimal  inverseRate { get; set; }  
   
                        public currencyDetails(string code, string name, string rate, string date, string inverseRate)  
                        {      
                            this      .code = code;      
                            this      .name = name;      
                            this      .rate =       decimal      .Parse(rate, System.Globalization.NumberStyles.Float);      
                            this      .dateString = date;      
                            this      .inverseRate =       decimal      .Parse(inverseRate, System.Globalization.NumberStyles.Float);      
                        }      
   
                        public override  string ToString()  
                        {      
                            return this.code + " - " +  this.name;  
                        }      
   
                    }      
   
      }  

Conclusion

The NuGet package Newtonsoft.Json makes working with raw JSON a simple task. It's easy to deserialize the JSON string into a Dictionary (in this case Of String, currencyDetails). 
Working with currency rates that are updated every day as raw JSON can make creating a simple currency converter an easy task.

Download

Download here...