【问题标题】:Binance API Invalid JSON Syntax on Kline/Candlestick data币安 API 在 Kline/Candlestick 数据上的 JSON 语法无效
【发布时间】:2022-08-14 18:57:46
【问题描述】:

客观的:使用JSON UtilsBinance REST API 生成C# 类,以便从交换中反序列化数据。

到目前为止,我已经使用 JSON Utils 实现了所有 C# 类,以便反序列化来自 exhange 的数据。除一个以外的所有(K线/烛台数据)

问题:当我在 JSON Utils 中粘贴下面的代码时,出现错误:无效的 JSON 语法

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

这是有效的 JSON 文件以及如何使用此输出生成 C# 类以反序列化数据?

编辑

根据你的所有陈述(尤其是。怪诞的),如果有人需要,这里是来源:

class B_KlineData
{
        public long openTime { get; set; }
        public string openPrice { get; set; }
        public string highPrice { get; set; }
        public string lowPrice { get; set; }
        public string closePrice { get; set; }
        public string volume { get; set; }
        public long closeTime { get; set; }
        public string quoteAssetVolume { get; set; }
        public long numberOfTrades { get; set; }
        public string baseVolume { get; set; }
        public string quoteVolume { get; set; }
        public string ignore { get; set; }

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

            foreach (var array in root.EnumerateArray())
            {
                yield return new B_KlineData
                {
                    openTime = array[0].GetInt64(),
                    openPrice = array[1].GetString(),
                    highPrice = array[2].GetString(),
                    lowPrice = array[3].GetString(),
                    closePrice = array[4].GetString(),
                    volume = array[5].GetString(),
                    closeTime = array[6].GetInt64(),
                    quoteAssetVolume = array[7].GetString(),
                    numberOfTrades = array[8].GetInt64(),
                    baseVolume = array[9].GetString(),
                    quoteVolume = array[10].GetString(),
                    ignore = array[11].GetString()
                };
            }

         }

}

调用方法

var jsonData= await market.KlineCandlestickData(\"BNBUSDT\", Interval.FIVE_MINUTE,null,null,2 );
            
IEnumerable<B_KlineData> bdata = B_KlineData.ParseBinanceResponse(jsonData);

            foreach (var item in bdata)
            {
                txtLog.Text += item.openTime.ToString() + \"\\n\";
                txtLog.Text += item.openPrice.ToString() + \"\\n\";
                txtLog.Text += item.highPrice.ToString() + \"\\n\";
                txtLog.Text += item.lowPrice.ToString() + \"\\n\";
                txtLog.Text += item.closePrice.ToString() + \"\\n\";
                txtLog.Text += item.volume.ToString() + \"\\n\";
                txtLog.Text += item.closeTime.ToString() + \"\\n\";
                txtLog.Text += item.quoteAssetVolume.ToString() + \"\\n\";
                txtLog.Text += item.numberOfTrades.ToString() + \"\\n\";
                txtLog.Text += item.baseVolume.ToString() + \"\\n\";
                txtLog.Text += item.quoteVolume.ToString() + \"\\n\";
                txtLog.Text += item.ignore.ToString() + \"\\n\";

            }

我不确定是否可以进一步优化此代码?

  • 它确实是有效的 JSON。它是一个数组数组。混合字符串值和数字虽然不是很好。根据所使用的序列化程序,它可能会或可能不会出现反序列化问题(JSON.NET 可以将其反序列化为double[][],但 System.Text.Json 必须先设置NumberHandling = JsonNumberHandling.AllowReadingFromString 才能反序列化)
  • 您可能必须进行一些低级别的 JSON 操作。这不是值的随机组合。每个指标都有具体的含义。并且数组可能用于节省空间(键在不需要时发生)。我怀疑任何自动“对象”反序列化器都可以正确处理这个问题。稍后我将发布一个关于如何处理它的示例。
  • 谢谢,我正在尝试以正确的方式定义类,但我不确定我是否做得对
  • 顺便说一句,我不认为你能用这个 JSON Utils 东西来实现这一点。它似乎有局限性,这是一个很好的例子。另外,作为旁注:您的int 字段绝对应该是@​​987654329@。
  • 正确,谢谢。我将尝试使用实时数据来查看我是否能够反序列化数据

标签: c# json json-deserialization binance-api-client


【解决方案1】:

所以 Binance 返回一个混合值数组。不过,这些不是随机值。通常你会得到一个对象数组,比如

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

但是如果数组很大,那么你就需要为那些实际上并不需要的键付出代价。您可以选择删除键并将该对象转换为数组,其中每个索引都有具体含义。这就是币安所做的。

不幸的是,典型的自动 Json 反序列化器(无论是否适用于 C#)不适用于此类序列化变体。一种方法是将其反序列化为object[][] 双数组,但这很尴尬且效率低下(装箱和其他不必要的分配),您仍然必须将该双数组转换为B_KlineData 对象。专业的方法是手动进行低级 Json 操作。假设您使用 System.Text.Json 它可以按如下方式完成:

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(),
            ...
        };
    }

}

所以你可以看到很多手动工作(你必须手动指定每个索引的含义)。但是,如果您最终想将其反序列化为B_KlineData,无论如何您都无法逃避它。好吧,它可以在某种程度上自动化,但是 AFAIK 没有 Json lib 这样做。不过我可能是错的。

顺便说一句,您的 int 字段应该是 long。您还可以在 ParseBinanceResponse 函数中添加适当的验证。

请注意,其他包(例如 Newtonsoft.Json)也应该允许低级别的 Json 操作。总体思路保持不变。

【讨论】:

  • 感谢您非常清楚的解释。将使用您提供的示例和使用 Newtonsoft.Json 尝试两种方式。
【解决方案2】:

您可以像这样将此类数据反序列化为 c# 类:

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

【讨论】:

    猜你喜欢
    • 2021-09-16
    • 2018-12-07
    • 1970-01-01
    • 2018-05-26
    • 2015-07-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多