다음을 통해 공유


VB.Net - 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...

Imports System.Net
Imports Newtonsoft.Json
 
Public Class  Form1
    Dim codes() As String
    Dim rates() As Decimal
    Dim inverse() As Decimal
 
    Private Sub  Form1_Load(sender As  Object, e As EventArgs) Handles MyBase.Load
        Dim client As New  WebClient
        Dim rawResponseString As String  = 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
        Dim jsonResulttodict As Dictionary(Of String, currencyDetails) = JsonConvert.DeserializeObject(Of Dictionary(Of 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
        codes = jsonResulttodict.Select(Function(kvp) kvp.Value.code).ToArray
        Dim tempCodes() As String  = DirectCast(codes.Clone, String())
        rates = jsonResulttodict.Select(Function(kvp) kvp.Value.rate).ToArray
        inverse = jsonResulttodict.Select(Function(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(Function(kvp) kvp.Value).OrderBy(Function(cd) cd.ToString).ToArray
        cboTo.DataSource = jsonResulttodict.Select(Function(kvp) kvp.Value).OrderBy(Function(cd) cd.ToString).ToArray
 
        'To ensure conversion takes place ASAP
        For Each  ctrl As  Control In  Me.Controls
            If ctrl Is nudAmount Then Continue For
            AddHandler ctrl.Click, AddressOf ctrls_Click
        Next
        AddHandler Me.Click, AddressOf  ctrls_Click
 
    End Sub
 
    Private Sub  ctrls_Click(sender As Object, e As  EventArgs)
        If sender Is Me  Then lblResults.Select()
        DirectCast(sender, Control).Select()
    End Sub
 
    Private Sub  inputs_ValuesChanged(sender As Object, e As  EventArgs) Handles  nudAmount.ValueChanged, cboFrom.SelectedIndexChanged, cboTo.SelectedIndexChanged,
                                                                                nudAmount.Leave, cboFrom.Leave, cboTo.Leave
        If cboFrom.SelectedIndex < 0 Or cboTo.SelectedIndex < 0 Or nudAmount.Value = 0D Then 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 - "  & DirectCast(cboFrom.SelectedItem, currencyDetails).dateString
    End Sub
 
    'This just paints some contrasting borders, in 
    'keeping with the systemcolors contrasting theme
    Private Sub  Form1_Paint(sender As Object, e As  PaintEventArgs) Handles Me.Paint
        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)
    End Sub
 
End Class

The Table Class

Public Class  Table
    Private Shared  values()() As  Decimal
 
    Public Shared  Sub createArray(codes() As String, rates() As  Decimal, inverse() As Decimal)
        'When complete, each cell of the table contains the value
        'for one 'From' unit's value in 'To' units
        ReDim values(codes.GetUpperBound(0))
        For x As Integer  = 0 To  codes.Length - 1
            ReDim values(x)(codes.GetUpperBound(0))
            values(x)(0) = rates(x)
            values(0)(x) = inverse(x)
            values(x)(x) = 1D
        Next x
        For c As Integer  = 1 To  codes.Length - 1
            For r As Integer  = 1 To  codes.Length - 1
                values(r)(c) = CDec(values(0)(c) / values(0)(r))
            Next
        Next
    End Sub
 
    Public Shared  Function getValueAt(c As Integer, r As  Integer) As Decimal
        Return values(r)(c)
    End Function
 
End Class

The currencyDetails Class

Public Class  currencyDetails
    Public Property  code As  String
    Public Property  name As  String
    Public Property  rate As  Decimal
    Public Property  dateString As  String
    Public Property  inverseRate As  Decimal
 
    Public Sub  New(code As String, name As  String, rate As String, [date] As  String, inverseRate As String)
        Me.code = code
        Me.name = name
        Me.rate = CDec(rate)
        Me.dateString = [date]
        Me.inverseRate = CDec(inverseRate)
    End Sub
 
    Public Overrides  Function ToString() As String
        Return Me.code & " - " &  Me.name
    End Function
 
End Class

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...