Reputation: 1
I've read numerous threads asking similar questions but have been unable to tie it all together.
I have an API feeding a string here: https://apiv2.bitcoinaverage.com/constants/exchangerates/local
I would like to make this string usable and accessible. For example getting the USD to CAD rate.
I'm using RestSharp and Newtonsoft JSON in my code.
using Newtonsoft.Json;
using RestSharp;
First I used http://json2csharp.com/ to create a class (classes?) matching the string. EDIT: I've now solved this, and had to nest the classes properly, as per revised code;
class Exrates
{
public Rates rates { get; set; }
public string time { get; set; }
public class Rates
{
public MXN Mxn { get; set; }
public ILS Ils { get; set; }
public EUR Eur { get; set; }
public BRL Brl { get; set; }
public PLN Pln { get; set; }
public MYR Myr { get; set; }
public SEK Sek { get; set; }
public AUD Aud { get; set; }
public IDR Idr { get; set; }
public TRY Try { get; set; }
public RUB Rub { get; set; }
public JPY Jpy { get; set; }
public CAD Cad { get; set; }
public USD Usd { get; set; }
public GBP Gbp { get; set; }
public NZD Nzd { get; set; }
public CZK Czk { get; set; }
public SGD Sgd { get; set; }
public class MXN
{
public string name { get; set; }
public string rate { get; set; }
}
public class ILS
{
public string name { get; set; }
public string rate { get; set; }
}
public class EUR
{
public string name { get; set; }
public string rate { get; set; }
}
public class BRL
{
public string name { get; set; }
public string rate { get; set; }
}
public class PLN
{
public string name { get; set; }
public string rate { get; set; }
}
public class MYR
{
public string name { get; set; }
public string rate { get; set; }
}
public class SEK
{
public string name { get; set; }
public string rate { get; set; }
}
public class AUD
{
public string name { get; set; }
public string rate { get; set; }
}
public class IDR
{
public string name { get; set; }
public string rate { get; set; }
}
public class TRY
{
public string name { get; set; }
public string rate { get; set; }
}
public class RUB
{
public string name { get; set; }
public string rate { get; set; }
}
public class JPY
{
public string name { get; set; }
public string rate { get; set; }
}
public class CAD
{
public string name { get; set; }
public string rate { get; set; }
}
public class USD
{
public string name { get; set; }
public string rate { get; set; }
}
public class GBP
{
public string name { get; set; }
public string rate { get; set; }
}
public class NZD
{
public string name { get; set; }
public string rate { get; set; }
}
public class CZK
{
public string name { get; set; }
public string rate { get; set; }
}
public class SGD
{
public string name { get; set; }
public string rate { get; set; }
}
}
}
I then called the API and stored the response in a string;
var btcAvgClient = new RestClient();
btcAvgClient.BaseUrl = new Uri("https://apiv2.bitcoinaverage.com/constants/exchangerates/local");
IRestResponse response;
var request = new RestRequest();
response = btcAvgClient.Execute(request);
string btcAvg = response.Content;
I believe there are 1 or 2 steps remaining but I can't quite figure it out. How do I now convert this string to something usable?
Any help is appreciated!
Upvotes: 0
Views: 1176
Reputation: 2221
Should be too root object.
var beers = JsonConvert.DeserializeObject<RootObject>(response.Content);
Upvotes: 0
Reputation: 116785
Firstly, modify your data model to look like the following:
public class Rate
{
public string name { get; set; }
public decimal rate { get; set; }
}
public class RootObject
{
public Dictionary<string, Rate> rates { get; set; }
public string time { get; set; }
}
Next, introduce the following extension method:
public static partial class RateExtensions
{
public static bool TryGetConversion(this Dictionary<string, Rate> rates, string from, string to, out decimal rate)
{
Rate fromRate;
Rate toRate;
if (rates == null || !rates.TryGetValue(from, out fromRate))
{
rate = 0;
return false;
}
if (!rates.TryGetValue(to, out toRate))
{
rate = 0;
return false;
}
rate = toRate.rate / fromRate.rate;
return true;
}
}
Now, you can execute a typed request as follows. The typed request will automatically deserialize the response into your desired data model:
var btcAvgClient = new RestClient("https://apiv2.bitcoinaverage.com/");
var request = new RestRequest("constants/exchangerates/local");
// Execute the request and get the typed response
var response = btcAvgClient.Execute<RootObject>(request);
// Get the root object from the response.
RootObject data = response.Data;
And compute the conversion from USD to CAD as follows:
// Compute the converson from (e.g.) USD to CAD
var fromName = "USD";
var toName = "CAD";
decimal rate;
if (data.rates.TryGetConversion(fromName, toName, out rate))
{
Console.WriteLine("Conversion from {0} to {1} = {2}", fromName, toName, rate);
}
else
{
Console.WriteLine("Cannot get conversion from {0} to {1}.", fromName, toName);
}
On my computer this outputs
Conversion from USD to CAD = 1.36245
Which currently seems to be the correct number as confirmed by a Google search:
1 United States Dollar equals 1.36 Canadian Dollar
Notes:
Since this API might possibly return different currencies in the future, but with the same data for each, I defined rates
to be a Dictionary<string, Rate> rates
. The dictionary will capture all returned currency rates.
Your code will need to know the currency names to expect, but I believe these are standard.
Since we are doing currency conversions here I defined rate
to be a decimal
rather than a string
. The serializer will automatically deserialize the string value for "rate"
into a decimal.
To ensure your request was successful see How to idiomatically handle HTTP error codes when using RestSharp?.
Alternatively you could check the response.ErrorException
as shown in the Recommended Usage documentation page.
If you need to make async
requests see How should I implement ExecuteAsync with RestSharp on Windows Phone 7?.
RestSharp has a built-in JSON serializer but you could use Json.NET if you prefer. Simply get the response.Content
string and deserialize by doing:
// Execute the request and get the untyped (string) response
var response = btcAvgClient.Execute(request);
// Get the root object from the response.
RootObject data = Newtonsoft.Json.JsonConvert.DeserializeObject<RootObject>(response.Content);
Upvotes: 1