1

I am having trouble parsing a JSON from the Alpha Vantage API. The output of the JSON is as follows

{
"Realtime Currency Exchange Rate": {
    "1. From_Currency Code": "BTC",
    "2. From_Currency Name": "Bitcoin",
    "3. To_Currency Code": "CNY",
    "4. To_Currency Name": "Chinese Yuan",
    "5. Exchange Rate": "43211.50782620",
    "6. Last Refreshed": "2018-04-11 17:48:12",
    "7. Time Zone": "UTC"
   }
}

I am parsing it like this

using (var wc = new System.Net.WebClient())
            json = wc.DownloadString(link);
            dynamic stuff = JsonConvert.DeserializeObject(json);
            string test = stuff["Realtime Currency Exchange Rate"]["5. Exchange Rate"];

However when I run the code, I am getting this error

Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: 'Cannot perform runtime binding on a null reference'

Anyone have any idea? If I print the value in a textbox, the value shows up but afterwards it shows that error. I am coding in c#

Thanks

3
  • Why do you have spaces, why do you have a list. You should readjust your Json. Also, you should use . notation vs brackets to access the object data. Commented Apr 11, 2018 at 18:49
  • Alpha Vantage spits out the JSON so thats why there's spaces. Idt I can use dot notation because theres spaces. Commented Apr 11, 2018 at 19:05
  • If you look closer I bet your spaces are converted into underscores. Commented Apr 11, 2018 at 19:06

2 Answers 2

1

Try creating an object to serialize to and use the JsonProperty attribute to map the json properties to the C# properties:

public class RealtimeCurrencyExchangeRate 
{
  [JsonProperty("1. From_Currency Code")]
  public string CurrencyCode { get; set; }
}

Then use the correct type when deserializing.

var obj = JsonConvert.DeserializeObject<RealtimeCurrencyExchangeRate >(json);

References:

Spaces handling: Deserializing JSON when fieldnames contain spaces

DeserializeObject: https://www.newtonsoft.com/json/help/html/DeserializeObject.htm


Or, if you want to dynamically read the properties, you can create a custom contract resolver:

public class AlphaVantageApiContractResolver : DefaultContractResolver
{
    protected override string ResolvePropertyName(string propertyName)
    {
        // derive the C#property name from the JSON property name
        var cSharpPropertyName = propertyName; 
        // Remove all periods from the C#property name 
        cSharpPropertyName = cSharpPropertyName.Replace(".", "");
        // replace all spaces with underscores
        cSharpPropertyName = cSharpPropertyName .Replace(" ", "_");

        // The value you return should map to the exact C# property name in your class so you need to create classes to map to.
        return cSharpPropertyName; 
    }
}

and use this while deserializing:

var jsonSettings = new JsonSerializerSettings();
jsonSettings.ContractResolver = new AlphaVantageApiContractResolver();

var obj = JsonConvert.DeserializeObject<MyClass>(json, jsonSettings);

https://www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_Serialization_DefaultContractResolver.htm#!

You will still have to create classes that map to the objects but now you don't have to worry about the JsonProperty attribute on every property. Just remember to remove periods and replace spaces with underscores in your C# property names. You will also have to write some code to remove numbers at the beginning of property names because this isn't allowed in C#.


If you can't pre-define your classes, you will need to deserialize anonymous objects and work with that.

Sign up to request clarification or add additional context in comments.

5 Comments

And would I have to do that for each property name?
@Bautistf, do you want to read-only from the API or send data back as well?
I want to be able to get the exchange rate, convert that to a double then and multiply it with another value
@Bautistf, I added another option that will work more dynamically so you don't have to put [JsonProperty(..)] everywhere. This solution would be more difficult if you had to send data back to the API but you could make it work.
would you be able to explain to me the theory behind the code? I am having trouble wrapping my head around it.
0

Your issue more than likely stems from your JSON. Though your JSON is valid, you violate a couple of principals which may be affecting the binder.

  1. You have spaces for your property name, which are often translated into underscores.
  2. You have a period in your property name, this also may interfere with the dot notation.

You could do the approach recommended by Kyle to bind. If you would like to use dynamic, then you could fix the above, then do the following syntax.

dynamic json = JsonConvert.Deserialize<object>(...);
var value = json.realTimeCurrencyExchangeRate.fromCurrencyCode;

The C# binder doesn't like a period when you utilize dot notation and spaces, when they're translated with underscores. So you could use your space, but the translation may be different. You would need to look closer at your object.

2 Comments

I don't think he has any control over that API
That is a bummer, cause it is horrible

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.