Search code examples
c#arraysjsonjson.netjsonconvert

Deserializing JSON to C# Class


I'm calling an API that returns JSON data as follows (the array has around 500 items):

[
    [
        1571702400000,
        "8197.28000000",
        "8297.99000000",
        "8000.00000000",
        "8020.00000000",
        "34651.82866300",
        1571788799999,
        "283535483.41051363",
        384699,
        "16767.03682400",
        "137253195.95826291",
        "0"
    ],
    [
        1614816000000,
        "50349.37000000",
        "51773.88000000",
        "49010.10000000",
        "49653.85000000",
        "25551.11905400",
        1614902399999,
        "1280981565.05072601",
        731056,
        "12197.45497900",
        "611820740.21554123",
        "0"
    ]
]

I'm trying to parse this data using JsonConvert.DeserializeObject(result).

Both attempts I've tried (see below) produce the following error:

Error Message

Cannot deserialize the current JSON array (e.g. [1,2,3]) into type '...+CandleSticks' because the type requires a JSON object (e.g. {"name":"value"}) to deserialize correctly.

To fix this error either change the JSON to a JSON object (e.g. {"name":"value"}) or change the deserialized type to an array or a type that implements a collection interface (e.g. ICollection, IList) like List that can be deserialized from a JSON array. JsonArrayAttribute can also be added to the type to force it to deserialize from a JSON array. Path '', line 1, position 1.

Attempt #1:

public class CandleStick
{
    public List<List<object>> MyArray { get; set; } 
}
...
CandleStick myCandles = JsonConvert.DeserializeObject<CandleStick>(result);

Attempt #2:

public class CandleStick
{
    public long openTime { get; set; }
    public string open { get; set; }
    public string high { get; set; }
    public string low { get; set; }
    public string close { get; set; }
    public string volume { get; set; }
    public long closeTime { get; set; }
    public string quoteAssetVolume { get; set; }
    public int numberOfTrades { get; set; }
    public string takerBuyBaseAssetVolume { get; set; }
    public string takerBuyQuoteAssetVolume { get; set; }
    public string ignore { get; set; }
}
...
List<CandleStick> myCandles = (List<CandleStick>)JsonConvert.DeserializeObject(result, typeof(List<CandleStick>));

How should I parse the JSON data correctly into a C# class?

EDIT - UPDATE

I can now deserialize the "unhelpful" JSON as follows:

var arrays = JsonConvert.DeserializeObject<List<List<object>>>(result);
            IEnumerable<CandleStick> candles = from values in arrays
                               select new CandleStick
                               {
                                   openTime = Convert.ToInt64(values[0]),
                                   open = Convert.ToString(values[1]),
                                   high = Convert.ToString(values[2]),
                                   low = Convert.ToString(values[3]),
                                   close = Convert.ToString(values[4]),
                                   volume = Convert.ToString(values[5]),
                                   closeTime = Convert.ToInt64(values[6]),
                                   quoteAssetVolume = Convert.ToString(values[7]),
                                   numberOfTrades = Convert.ToInt32(values[8]),
                                   takerBuyBaseAssetVolume = Convert.ToString(values[9]),
                                   takerBuyQuoteAssetVolume = Convert.ToString(values[10]),
                                   ignore = Convert.ToString(values[11])
                               };

CandleStick cd = candles.ElementAt(0);

When I try to reference the elements of candles, I get an error msg saying that the expected string was not in the correct format.

Silly me! If I think about it more carefully the error message makes sense. My array was not converting one of the elements correctly. Now I can reference the data as expected - ElementAt(x) .ToList(), etc.


Solution

  • Your #1 attempt was nearly there.

    You can do:

    var arrays = JsonConvert.DeserializeObject<List<List<object>>>(json);
    

    but then you will have to do the mapping yourself:

    var candlesticks =
        from values in arrays
        select new CandleSticks
        {
            openTime = Convert.ToInt64(values[0]),
            open = Convert.ToString(values[1]),
            high = Convert.ToString(values[2]),
            ...
        };
    

    I know that most of the values are already in the right format, so at least for the strings you can probably get by with a case, like high = (string)values[2], but for the longs and ints you really want to use Convert, since small integer values might become ints and higher values might become longs, and then you can't simply cast.