Search code examples
c#jsonserialization

Deserialize Json Response With Unpredictable Dates As Headers


I am downloading stock pricing data in this format:

{"Meta Data": { "1. Information": "Intraday (5min) open, high, low, close prices and volume", "2. Symbol": "IBM", "3. Last Refreshed": "2023-08-01 19:55:00", "4. Interval": "5min", "5. Output Size": "Compact", "6. Time Zone": "US/Eastern" }, "Time Series (5min)": { "2023-08-01 19:55:00": { "1. open": "142.8100", "2. high": "143.1000", "3. low": "142.8100", "4. close": "142.8100", "5. volume": "230" }, "2023-08-01 19:45:00": { "1. open": "143.0000", "2. high": "143.0000", "3. low": "143.0000", "4. close": "143.0000", "5. volume": "50" },.........................}

I want to deserialize in C#.

The structure of the Meta Data is predictable, this piece is working.

But the dates are unpredictable, I don't know the exact dates coming with the response, and each date has five underlying variables.

I can't structure the JsonProperty items with the exact dates therefore, so how can I deserialize data like this?

My attempt:

 public class json_price
{

    [JsonProperty("Meta Data")]
    public headers Headers { get; set; }

    public class headers
    {
        [JsonProperty("1. Information")]
        public string s1 { get; set; }
        [JsonProperty("2. Symbol")]
        public string s2 { get; set; }
        [JsonProperty("3. Last Refreshed")]
        public string s3 { get; set; }
        [JsonProperty("4. Interval")]
        public string s4 { get; set; }
        [JsonProperty("5. Output Size")]
        public string s5 { get; set; }
        [JsonProperty("6. Time Zone")]
        public string s6 { get; set; }
    }


    [JsonProperty("Time Series 5min")]
    public priceheader ph { get; set; }


    // [JsonProperty("??????")] unknown date so can't refer to JsonProperty??
    public class priceheader
    {
        public datepricing[] dp { get; set; }
    }
             
    public class datepricing
    {

        [JsonProperty("1. open")]
        public long O { get; set; }
        [JsonProperty("2. high")]
        public long H { get; set; }
        [JsonProperty("3. low")]
        public long L { get; set; }
        [JsonProperty("4. close")]
        public long C { get; set; }
        [JsonProperty("5. volume")]
        public long V { get; set; }

    }

}

This yields a correctly populated Headers object but an empty "ph" object when I try to deserialize:

json_price results = JsonConvert.DeserializeObject<json_price>(output);

Thanks!


Solution

  • Using a dictionary works if you fix the types of datepricing properties

    json_price results = JsonConvert.DeserializeObject<json_price>(json);
    
    public class json_price
    {
        [JsonProperty("Meta Data")]
        public headers Headers { get; set; }
    
        [JsonProperty("Time Series (5min)")]
        public Dictionary<string, datepricing> ph { get; set; }
    }
    public class datepricing
    {
        [JsonProperty("1. open")]
        public double O { get; set; }
        [JsonProperty("2. high")]
        public double H { get; set; }
        [JsonProperty("3. low")]
        public double L { get; set; }
        [JsonProperty("4. close")]
        public double C { get; set; }
        [JsonProperty("5. volume")]
        public long V { get; set; }
    }
    

    but I don't like a DateTime property as a Dictionary key and prefer using a List

        var jObj=JObject.Parse(json);
        
        json_price results = jObj.ToObject<json_price>();
        
        foreach (JProperty prop in ((JObject) jObj["Time Series (5min)"]).Properties())
        {
            var dp=prop.Value.ToObject<datepricing>();
            dp.pricingDate= DateTime.Parse(prop.Name);
            results.ph.Add(dp);
        }
    
    public class json_price
    {
        [JsonProperty("Meta Data")]
        public headers Headers { get; set; }
    
        public List<datepricing> ph { get; set; } = new();
    }
    
    public class datepricing
    {
        public DateTime pricingDate { get; set; }
    
        // another properties
    }