1

I am building a economy simulation game using Unity and have the need to pull live exchange rates from and API. For this I am using fixer.io. I have implemented this using UnityWebRequest, see below my code:

using Newtonsoft.Json;
using System.Collections;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;

public class ExchangeRequest : MonoBehaviour
{
    private string url = "http://data.fixer.io/api/latest?access_key=**********";

    Text exchange;

    public void GetExchangeRates()
    {
        StartCoroutine(MakeRequest());
    }

    IEnumerator MakeRequest()
    {
        UnityWebRequest request = UnityWebRequest.Get(url);
        yield return request.SendWebRequest();

        if (request.isNetworkError || request.isHttpError)
        {
            Debug.Log(request.error);
        }
        else
        {
            Debug.Log("Received" + request.downloadHandler.text);
            var Rates = JsonConvert.DeserializeObject<Rates>(request.downloadHandler.text);

            exchange = GameObject.Find("MainText").GetComponent<Text>();
            exchange.text = Rates.ZAR.ToString();
        }
    }
}

and for parsing the JSON

public class Rates
{
    public double AED { get; set; }
    public double AFN { get; set; }
    public double ALL { get; set; }
    public double AMD { get; set; }
    public double ANG { get; set; }
    public double AOA { get; set; }
    public double ARS { get; set; }
    public double AUD { get; set; }
    public double AWG { get; set; }
    public double AZN { get; set; }
    public double BAM { get; set; }
    public double BBD { get; set; }
    public double BDT { get; set; }
    public double BGN { get; set; }
    public double BHD { get; set; }
    public double BIF { get; set; }
    public double BMD { get; set; }
    public double BND { get; set; }
    public double BOB { get; set; }
    public double BRL { get; set; }
    public double BSD { get; set; }
    public double BTC { get; set; }
    public double BTN { get; set; }
    public double BWP { get; set; }
    public double BYN { get; set; }
    public double BYR { get; set; }
    public double BZD { get; set; }
    public double CAD { get; set; }
    public double CDF { get; set; }
    public double CHF { get; set; }
    public double CLF { get; set; }
    public double CLP { get; set; }
    public double CNY { get; set; }
    public double COP { get; set; }
    public double CRC { get; set; }
    public double CUC { get; set; }
    public double CUP { get; set; }
    public double CVE { get; set; }
    public double CZK { get; set; }
    public double DJF { get; set; }
    public double DKK { get; set; }
    public double DOP { get; set; }
    public double DZD { get; set; }
    public double EGP { get; set; }
    public double ERN { get; set; }
    public double ETB { get; set; }
    public int EUR { get; set; }
    public double FJD { get; set; }
    public double FKP { get; set; }
    public double GBP { get; set; }
    public double GEL { get; set; }
    public double GGP { get; set; }
    public double GHS { get; set; }
    public double GIP { get; set; }
    public double GMD { get; set; }
    public double GNF { get; set; }
    public double GTQ { get; set; }
    public double GYD { get; set; }
    public double HKD { get; set; }
    public double HNL { get; set; }
    public double HRK { get; set; }
    public double HTG { get; set; }
    public double HUF { get; set; }
    public double IDR { get; set; }
    public double ILS { get; set; }
    public double IMP { get; set; }
    public double INR { get; set; }
    public double IQD { get; set; }
    public double IRR { get; set; }
    public double ISK { get; set; }
    public double JEP { get; set; }
    public double JMD { get; set; }
    public double JOD { get; set; }
    public double JPY { get; set; }
    public double KES { get; set; }
    public double KGS { get; set; }
    public double KHR { get; set; }
    public double KMF { get; set; }
    public double KPW { get; set; }
    public double KRW { get; set; }
    public double KWD { get; set; }
    public double KYD { get; set; }
    public double KZT { get; set; }
    public double LAK { get; set; }
    public double LBP { get; set; }
    public double LKR { get; set; }
    public double LRD { get; set; }
    public double LSL { get; set; }
    public double LTL { get; set; }
    public double LVL { get; set; }
    public double LYD { get; set; }
    public double MAD { get; set; }
    public double MDL { get; set; }
    public double MGA { get; set; }
    public double MKD { get; set; }
    public double MMK { get; set; }
    public double MNT { get; set; }
    public double MOP { get; set; }
    public double MRO { get; set; }
    public double MUR { get; set; }
    public double MVR { get; set; }
    public double MWK { get; set; }
    public double MXN { get; set; }
    public double MYR { get; set; }
    public double MZN { get; set; }
    public double NAD { get; set; }
    public double NGN { get; set; }
    public double NIO { get; set; }
    public double NOK { get; set; }
    public double NPR { get; set; }
    public double NZD { get; set; }
    public double OMR { get; set; }
    public double PAB { get; set; }
    public double PEN { get; set; }
    public double PGK { get; set; }
    public double PHP { get; set; }
    public double PKR { get; set; }
    public double PLN { get; set; }
    public double PYG { get; set; }
    public double QAR { get; set; }
    public double RON { get; set; }
    public double RSD { get; set; }
    public double RUB { get; set; }
    public double RWF { get; set; }
    public double SAR { get; set; }
    public double SBD { get; set; }
    public double SCR { get; set; }
    public double SDG { get; set; }
    public double SEK { get; set; }
    public double SGD { get; set; }
    public double SHP { get; set; }
    public double SLL { get; set; }
    public double SOS { get; set; }
    public double SRD { get; set; }
    public double STD { get; set; }
    public double SVC { get; set; }
    public double SYP { get; set; }
    public double SZL { get; set; }
    public double THB { get; set; }
    public double TJS { get; set; }
    public double TMT { get; set; }
    public double TND { get; set; }
    public double TOP { get; set; }
    public double TRY { get; set; }
    public double TTD { get; set; }
    public double TWD { get; set; }
    public double TZS { get; set; }
    public double UAH { get; set; }
    public double UGX { get; set; }
    public double USD { get; set; }
    public double UYU { get; set; }
    public double UZS { get; set; }
    public double VEF { get; set; }
    public double VND { get; set; }
    public double VUV { get; set; }
    public double WST { get; set; }
    public double XAF { get; set; }
    public double XAG { get; set; }
    public double XAU { get; set; }
    public double XCD { get; set; }
    public double XDR { get; set; }
    public double XOF { get; set; }
    public double XPF { get; set; }
    public double YER { get; set; }
    public double ZAR { get; set; }
    public double ZMK { get; set; }
    public double ZMW { get; set; }
    public double ZWL { get; set; }
}

public class ExchangeRates
{
    public bool success { get; set; }
    public int timestamp { get; set; }
    public string date { get; set; }
    public double rates { get; set; }
}

The Debug.Log("Received" + request.downloadHandler.text); returns the API data, but when the function is called all the values show up as 0 in the debugger - Breakpoint with debugger, and this causes the string to update to "0".

Can anyone please advise what I could be doing wrong?

Many Thanks.

DedSec
  • 53
  • 2
  • 8
  • Which version of Json.net are you using? The stock NuGet implementation? Or one built specificaly for unity? Also, what target platform? Json.net uses dynamic code execution by default which isn't allowed on some platforms (like iOS). There's unity-specific implementation of Json.Net that I use and haven't had issues with: https://assetstore.unity.com/packages/tools/input-management/json-net-for-unity-11347 . I'd start there if I were you. – Basic Sep 06 '20 at 09:15
  • @Basic I am using the latest JSON.NET For Unity from the Asset Store (same as the link you provided). Unity version 2020.1.4f1, target platform is Windows, architecture is x86_64. The issue is not pulling the API data, that I can get. I'm assuming it's the deserializing that's the issue since the values show up as 0. – DedSec Sep 06 '20 at 09:30
  • Ok, the guaranteed to work but time-consuming option is to remove the json.net dll from your project and instead unzip the json.net source into your project. That will allow you to step into the json.net code. You should be able to achieve the same by having the correct symbols (.pdb) present and disabling "Just My Code" in VS debugging options (but I haven't tried it with Json.Net so can't say it ships with the symbols). But before sinking any time into that... Try creating a minimal test case with one double and a tiny hard coded json string, just to make sure there's no errors in your test. – Basic Sep 06 '20 at 11:56
  • @Basic I figured out what the issue was. In the API I was using there were no spaces after any of the `:` in the JSON output so it could not physically ready any data. I tested with a few sample API's and was only able to get data from those with spaces after the `:` symbol ie `"userId": 1;` vs `"username":kathy;` or `"username":"kathy";` Any suggestions on this? – DedSec Sep 06 '20 at 16:36
  • @Basic So I found an exchange rate API with spaces after the `:` symbol but this is still returning 0 in the debugger - https://openexchangerates.org/api/latest.json?app_id=05c289988485451c9532fe64d73679b9 This API actually returns the data in the debugger - https://jsonplaceholder.typicode.com/todos/1 Am I missing something else? – DedSec Sep 06 '20 at 17:19

1 Answers1

2

So it was really simple actually.

The data I was trying to fetch was a list inside the JSON output this is why the initial method did not work.

{
  "disclaimer": "Usage subject to terms: https://openexchangerates.org/terms",
  "license": "https://openexchangerates.org/license",
  "timestamp": 1599411203,
  "base": "USD",
  "rates": {
    "AUD": 1.372721,
    "EUR": 0.844691,
    "GBP": 0.752474,
    "JPY": 106.24548164,
    "USD": 1,
    "ZAR": 16.58301
  }
}

I updated JSON parsor to include a class for the "rates" list in the JSON output:

public class ExchangeRates
{
    public Rates rates { get; set; }
}

public class Rates
{
    public double AUD { get; set; }
    public double EUR { get; set; }
    public double GBP { get; set; }
    public double JPY { get; set; }
    public double USD { get; set; }
    public double ZAR { get; set; }
}

Then I updated my function to deserialize the list in which I could parse the individual rates:

var xr = JsonConvert.DeserializeObject<ExchangeRates>(request.downloadHandler.text);
exchange = GameObject.Find("MainText").GetComponent<Text>();
exchange.text = xr.rates.ZAR.ToString();

Now I am able to get the JSON data.

DedSec
  • 53
  • 2
  • 8