Home > Enterprise >  Binance API Invalid JSON Syntax on Kline/Candlestick data
Binance API Invalid JSON Syntax on Kline/Candlestick data

Time:08-12

Objective: Generate C# classes using JSON Utils for Binance REST API in order to deserialize data from exchange.

So far i have implemented all C# classes using JSON Utils in order to deserialize data from exhange. All except one (Kline/Candlestick data)

Problem: When i paste code from bellow in JSON Utils i am getting error: Invalid JSON Syntax

[
    [
        1660284300000,
        "323.50000000",
        "323.70000000",
        "322.40000000",
        "322.40000000",
        "757.16400000",
        1660284599999,
        "244731.13410000",
        536,
        "205.39900000",
        "66395.15700000",
        "0"
    ]
]

Is this valid JSON file and how to generate C# Class using this output in order to deserialize data?

If not, i am very interested why Binance decided to output Kline/Candlestick data in format that is not JSON and all the others are?

UPDATE: Should the proper class definition for this JSON file look like this:

public class B_KlineData
{

    [JsonProperty("Open time")]
    public int openTime { get; set; }

    [JsonProperty("Open")]
    public string open { get; set; }

    [JsonProperty("High")]
    public string high { get; set; }

    [JsonProperty("Low")]
    public string low { get; set; }

    [JsonProperty("Close")]
    public string close { get; set; }

    [JsonProperty("Volume")]
    public string volume { get; set; }

    [JsonProperty("Close time")]
    public int closeTime { get; set; }

    [JsonProperty("Quote asset volume")]
    public string quoteAssetVolume { get; set; }

    [JsonProperty("Number of trades")]
    public int numberOfTrades { get; set; }

    [JsonProperty("Taker buy base asset volume")]
    public string baseVolume { get; set; }

    [JsonProperty("Taker buy quote asset volume")]
    public string quoteVolume { get; set; }

    [JsonProperty("Ignore")]
    public string ignore { get; set; }
}

CodePudding user response:

So Binance returns an array of arrays of mixed values. These are not random values though. Typically you would get an array of objects like

[ { "openTime": 1660284300000, ... } ]

but if the array is big then you pay the price for those keys, which are not really needed. You can choose to drop keys and turn that object into an array, where each index has a concrete meaning. And this is what Binance does.

Unfortunately, typical automatic Json deserializers (for C# or not) don't work with such serialization variants. One way would be to deserialize this into object[][] double array, but this is awkward and also inefficient (boxing and other unnecessary allocations) and you still have to convert that double array into B_KlineData objects. The pro way is to do manual low level Json manipulation. Assuming you use System.Text.Json it can be done as follows:

using System.Text.Json;

public static IEnumerable<B_KlineData> ParseBinanceResponse(string json)
{
    var jsonDoc = JsonDocument.Parse(json);
    var root = jsonDoc.RootElement;

    foreach (var array in root.EnumerateArray())
    {
        yield new B_KlineData
        {
            openTime = array[0].GetInt64(),
            open = array[1].GetString(),
            high = array[2].GetString(),
            low = array[3].GetString(),
            ...
        };
    }

}

So as you can see lots of manual work (you have to specify the meaning of each index manually). But you can't run away from it anyway, if ultimately you want to deserialize this into B_KlineData. Well, it could be automatized somewhat, but AFAIK no Json lib does this. I might be wrong though.

Btw, your int fields should be long. And you can also add a proper validation inside ParseBinanceResponse function.

Note that other packages (e.g. Newtonsoft.Json) should allow low level Json manipulation as well. The general idea stays the same though.

CodePudding user response:

You can deserialize like this data to c# class like this:

 public class ClassName
{
    public object[][] PropertyName{ get; set; }
}
  • Related