You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在C#中反序列化Kraken的OHLC JSON数据遇到问题

Solving Kraken OHLC API JSON Deserialization in C#

Hey there! Let's tackle this Kraken OHLC API deserialization issue you're having. I've dealt with similar quirks in Kraken's API responses before, so here's a step-by-step breakdown to get you sorted:

First, Understand the Kraken Response Structure

Unlike Cryptocompare's straightforward object-based JSON, Kraken returns OHLC data as arrays of values (no property names) and wraps the data under a dynamic key (e.g., XETHZUSD for your ETHUSD pair). A sample snippet looks like this:

{"error":[],"result":{"XETHZUSD":[[1699996800,"1800.10","1802.50","1799.80","1801.20","12.3456","1800.75"],...],"last":1699998600}}

This is the main reason your standard deserialization approach isn't working—you can't map anonymous arrays directly to a strongly-typed class without extra handling.

Step 1: Create Your C# Models

We'll need two classes: one to handle the top-level response, and another to represent a single OHLC candle. The key here is using JsonExtensionData (for System.Text.Json) or leveraging Newtonsoft.Json's JObject to handle the dynamic trading pair key.

For System.Text.Json:

using System.Text.Json.Serialization;

public class OhlcCandle
{
    public long Timestamp { get; set; }
    public decimal Open { get; set; }
    public decimal High { get; set; }
    public decimal Low { get; set; }
    public decimal Close { get; set; }
    public decimal Volume { get; set; }
    public decimal WeightedAverage { get; set; }
}

public class KrakenOhlcResponse
{
    public List<string> Error { get; set; } = new List<string>();
    public KrakenOhlcResult Result { get; set; } = new KrakenOhlcResult();
}

public class KrakenOhlcResult
{
    [JsonPropertyName("last")]
    public long LastUpdateTimestamp { get; set; }

    // Catch-all for the dynamic trading pair key
    [JsonExtensionData]
    public Dictionary<string, JsonElement> PairData { get; set; } = new Dictionary<string, JsonElement>();
}

For Newtonsoft.Json (Json.NET):

using Newtonsoft.Json;

public class OhlcCandle
{
    public long Timestamp { get; set; }
    public decimal Open { get; set; }
    public decimal High { get; set; }
    public decimal Low { get; set; }
    public decimal Close { get; set; }
    public decimal Volume { get; set; }
    public decimal WeightedAverage { get; set; }
}

public class KrakenOhlcResponse
{
    public List<string> Error { get; set; } = new List<string>();
    public KrakenOhlcResult Result { get; set; } = new KrakenOhlcResult();
}

public class KrakenOhlcResult
{
    [JsonProperty("last")]
    public long LastUpdateTimestamp { get; set; }

    // We'll handle the dynamic key via JObject parsing instead
}

Step 2: Deserialize and Map the Data

Now we'll take the raw JSON response, deserialize it, then manually map the array values to your OhlcCandle class.

System.Text.Json Implementation:

using System.Text.Json;

// Fetch the API response (use HttpClient in your actual code)
var httpClient = new HttpClient();
var responseJson = await httpClient.GetStringAsync("https://api.kraken.com/0/public/OHLC?pair=ETHUSD&interval=30");

// Deserialize to our response model
var krakenResponse = JsonSerializer.Deserialize<KrakenOhlcResponse>(responseJson);

// Check for API errors first
if (krakenResponse.Error.Any())
{
    Console.WriteLine($"Kraken API Error: {string.Join(", ", krakenResponse.Error)}");
    return;
}

// Get the first (and only, since you requested one pair) set of OHLC data
var ohlcArray = krakenResponse.Result.PairData
    .First()
    .Value
    .Deserialize<List<object[]>>();

// Map the array values to our OhlcCandle class
var ohlcCandles = ohlcArray.Select(arr => new OhlcCandle
{
    Timestamp = (long)arr[0],
    Open = decimal.Parse(arr[1].ToString()),
    High = decimal.Parse(arr[2].ToString()),
    Low = decimal.Parse(arr[3].ToString()),
    Close = decimal.Parse(arr[4].ToString()),
    Volume = decimal.Parse(arr[5].ToString()),
    WeightedAverage = decimal.Parse(arr[6].ToString())
}).ToList();

// Now you have a strongly-typed list of OHLC candles!

Newtonsoft.Json Implementation:

using Newtonsoft.Json.Linq;

// Fetch the API response
var httpClient = new HttpClient();
var responseJson = await httpClient.GetStringAsync("https://api.kraken.com/0/public/OHLC?pair=ETHUSD&interval=30");

// Parse to JObject for flexible handling
var jObject = JObject.Parse(responseJson);

// Check for errors
var errors = jObject["error"].ToObject<List<string>>();
if (errors.Any())
{
    Console.WriteLine($"Kraken API Error: {string.Join(", ", errors)}");
    return;
}

// Get the result object and find the trading pair key (skip the "last" property)
var result = jObject["result"];
var pairKey = result.Properties().First(p => p.Name != "last").Name;
var ohlcArray = result[pairKey].ToObject<List<object[]>>();

// Map to OhlcCandle
var ohlcCandles = ohlcArray.Select(arr => new OhlcCandle
{
    Timestamp = (long)arr[0],
    Open = decimal.Parse(arr[1].ToString()),
    High = decimal.Parse(arr[2].ToString()),
    Low = decimal.Parse(arr[3].ToString()),
    Close = decimal.Parse(arr[4].ToString()),
    Volume = decimal.Parse(arr[5].ToString()),
    WeightedAverage = decimal.Parse(arr[6].ToString())
}).ToList();

Key Notes to Remember

  • Dynamic Pair Key: Kraken uses standardized pair codes (e.g., ETHUSD becomes XETHZUSD), but since you're requesting a single pair, you can safely grab the first non-"last" property in the result.
  • Array Mapping: The OHLC data is ordered as [timestamp, open, high, low, close, volume, weighted average]—make sure your index positions match this order.
  • Data Type Safety: Kraken returns numeric values as strings or floats, so parsing to decimal ensures you avoid floating-point precision issues.

内容的提问来源于stack exchange,提问作者Yeahson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 08:18:23