Search code examples
c#jsonjson-deserialization

Deserialize Json when name is dynamic


I use this simple API, https://exchangeratesapi.io/ and I test with this uri: https://api.exchangeratesapi.io/history?start_at=2018-01-01&end_at=2018-03-01&symbols=SEK. I want to deserialize the 'rates' part. Here is one response sample enter image description here

And here is the code

public class ExchangeRate
{
    [JsonProperty(PropertyName = "end_at", Order = 1)]
    public DateTime EndAt { get; set; }

    [JsonProperty(PropertyName = "start_at", Order = 2)]
    public DateTime StartAt { get; set; }

    [JsonProperty(PropertyName = "rates", Order = 3)]
    public Dictionary<string, Rate> Rates { get; set; }

    [JsonProperty(PropertyName = "base", Order = 4)]
    public string Base { get; set; }
}

public class Rate
{
    [JsonProperty]
    public Dictionary<string, double> Fields{ get; set; }
}

or

public class Rate
{
    [JsonProperty]
    public string CurrencyName { get; set; }
    [JsonProperty]
    public double CurrencyRate { get; set; }
}

And I deserilize it like this

var result = Newtonsoft.Json.JsonConvert.DeserializeObject<ExchangeRateHistory>(response.Content);

My problem is that that Fields is null. Does anyone have any suggestion?


Solution

  • If your key/value pair are not fixed and data must be configurable then Newtonsoft.json has one feature that to be use here and that is [JsonExtensionData]. Read more

    Extension data is now written when an object is serialized. Reading and writing extension data makes it possible to automatically round-trip all JSON without adding every property to the .NET type you’re deserializing to. Only declare the properties you’re interested in and let extension data do the rest.

    In your case rates key have value as dynamic data so your Rate class will be

    public class Rate
    {
        [JsonExtensionData]
        public Dictionary<string, JToken> Fields { get; set; }
    }
    

    And then you can deserialize your response content as

    var result = Newtonsoft.Json.JsonConvert.DeserializeObject<ExchangeRate>(response.Content);