Deserializing JSON from TD Ameritrade

Viewed 208

I am pulling in quote data from TD Ameritrade's API, and it's generating the following JSON:

{
  "AAPL": {
    "52WkHigh": 145.09,
    "52WkLow": 53.1525,
    "askId": "P",
    "askPrice": 121.08,
    "askSize": 1700,
    "assetMainType": "EQUITY",
    "assetType": "EQUITY",
    "bidId": "P",
    "bidPrice": 121.06,
    "bidSize": 600,
    "bidTick": " ",
    "closePrice": 121.03,
    "cusip": "037833100",
    "delayed": "false",
    "description": "Apple Inc. - Common Stock",
    "digits": 4,
    "divAmount": 0.82,
    "divDate": "2021-02-05 00:00:00.000",
    "divYield": 0.68,
    "exchange": "q",
    "exchangeName": "NASD",
    "highPrice": 121.17,
    "lastId": "D",
    "lastPrice": 121.08,
    "lastSize": 200,
    "lowPrice": 119.16,
    "marginable": "true",
    "mark": 121.03,
    "markChangeInDouble": 0.0,
    "markPercentChangeInDouble": 0.0,
    "nAV": 0.0,
    "netChange": 0.05,
    "netPercentChangeInDouble": 0.0413,
    "openPrice": 120.4,
    "peRatio": 32.9702,
    "quoteTimeInLong": 1615597198023,
    "regularMarketLastPrice": 121.03,
    "regularMarketLastSize": 7,
    "regularMarketNetChange": 0.0,
    "regularMarketPercentChangeInDouble": 0.0,
    "regularMarketTradeTimeInLong": 1615582801729,
    "securityStatus": "Normal",
    "shortable": "true",
    "symbol": "AAPL",
    "totalVolume": 88105050,
    "tradeTimeInLong": 1615597198932,
    "volatility": 0.0085
  }
}

Class created from JSON:

public class Quote
{
    public float _52WkHigh { get; set; }
    public float _52WkLow { get; set; }
    public string askId { get; set; }
    public float askPrice { get; set; }
    public int askSize { get; set; }
    public string assetMainType { get; set; }
    public string assetType { get; set; }
    public string bidId { get; set; }
    public float bidPrice { get; set; }
    public int bidSize { get; set; }
    public string bidTick { get; set; }
    public float closePrice { get; set; }
    public string cusip { get; set; }
    public string delayed { get; set; }
    public string description { get; set; }
    public int digits { get; set; }
    public float divAmount { get; set; }
    public string divDate { get; set; }
    public float divYield { get; set; }
    public string exchange { get; set; }
    public string exchangeName { get; set; }
    public float highPrice { get; set; }
    public string lastId { get; set; }
    public float lastPrice { get; set; }
    public int lastSize { get; set; }
    public float lowPrice { get; set; }
    public string marginable { get; set; }
    public float mark { get; set; }
    public float markChangeInDouble { get; set; }
    public float markPercentChangeInDouble { get; set; }
    public float nAV { get; set; }
    public float netChange { get; set; }
    public float netPercentChangeInDouble { get; set; }
    public float openPrice { get; set; }
    public float peRatio { get; set; }
    public long quoteTimeInLong { get; set; }
    public float regularMarketLastPrice { get; set; }
    public int regularMarketLastSize { get; set; }
    public float regularMarketNetChange { get; set; }
    public float regularMarketPercentChangeInDouble { get; set; }
    public long regularMarketTradeTimeInLong { get; set; }
    public string securityStatus { get; set; }
    public string shortable { get; set; }
    public string symbol { get; set; }
    public int totalVolume { get; set; }
    public long tradeTimeInLong { get; set; }
    public float volatility { get; set; }
}

I am calling a Python Script to get the JSON data, which then redirects to my C# app. However, when I deserialize it, no data is populating:

    public void GetQuotes(string symbol)
    {
        var errors = "";
        var results = "";
        this.psi.Arguments = $"\"{this.script}\" -q {symbol}";
        Quote quote;

        using (var process = Process.Start(psi))
        {
            errors = process.StandardError.ReadToEnd();
            results = process.StandardOutput.ReadToEnd();
            Debug.Print(results);
            
            quote = JsonConvert.DeserializeObject<Quote>(results);
            
        }

        MessageBox.Show(quote.symbol);
    }

I have been able to deserialize Json with relatively consistent success, but I can't figure out why I'm loading in blank objects from this JSON.

2 Answers

You need to create a root object that contains your Quote object.

public class RootObject 
{
  public Quote AAPL { get;set;}
}

and deserialize to this,

var rootObject = JsonConvert.DeserializeObject<RootObject>(results);
Quote quote = rootObject.AAPL;

When you deserialize to Quote, you are getting nulls because there is no property in the original json that matches with any of the Quote properties. Since your JSON contains 1 property (AAPL) and its value is of type Quote, you have to deserialize to RootObject.

Based on your point on variable key, you should deserialize to Dictionary<string, Quote>.

var obj = JsonConvert.DeserializeObject<Dictionary<string, Quote>>(results);
Quote quote = obj.FirstOrDefault().Value;

You can also list all keys and use foreach loop but if you know there will always be only one key, FirstOrDefault() will work as well.

Thanks to Jawad for the quick hint. Because 'AAPL' is an ever-changing key, I had to deserialize the JSON into a Dictionary<string, Quote> to get the data populating:

    public void GetQuotes(string symbol)
    {
        var errors = "";
        var results = "";
        this.psi.Arguments = $"\"{this.script}\" -q {symbol}";
        Dictionary<string, Quote> quotes;

        using (var process = Process.Start(psi))
        {
            errors = process.StandardError.ReadToEnd();
            results = process.StandardOutput.ReadToEnd();
            Debug.Print(results);

            
            quotes = JsonConvert.DeserializeObject<Dictionary<string, Quote>>(results);
        }
    }
Related