如何创建通用模型来反序列化来自外部API的响应

问题描述 投票:0回答:1

我正在创建一个端点来从加密货币市场获取特定加密货币的价格。 我正在使用 Kucoin 和 Binance 的 API。当我收到回复时,两个回复中都有

bids
asks
字段。两个 API 响应都有不同的结构,但是我只需要这个字段。如何创建通用模型并将 api 的响应反序列化到该模型中?

我当前的代码:

// OrderBookResponse
public class OrderBookResponse
{
    public OrderBookData Data { get; set; }
}

// OrderBookData
public class OrderBookData
{
    public List<List<string>> Bids { get; set; }
    public List<List<string>> Asks { get; set; }
}

库币服务

    public ExchangeRate GetExchangeRateAsync(GetRatesModel getRates)
    {
        var uriBuilder = new UriBuilder(CryptoExchangeUrls.KucoinApi)
        {
            Path = "/api/v1/market/orderbook/level2_20",
            Query = $"symbol={getRates.BaseCurrency.ToUpper()}-{getRates.QuoteCurrency.ToUpper()}"
        };

        using var client = new HttpClient();

        HttpResponseMessage response = client.GetAsync(uriBuilder.Uri).Result;

        if (!response.IsSuccessStatusCode)
        {
            throw new Exception($"HTTP request failed with status code {response.StatusCode}");
        }

        OrderBookResponse deserializedResponse = response.Content.ReadFromJsonAsync<OrderBookResponse>().Result;

        ExchangeRate exchangeRate = new ExchangeRate()
        {
            ExchangeName = "Kucoin",
            Rate = PriceHelper.GetAveragePrice(deserializedResponse.Data)
        };

        return exchangeRate;
    }

币安服务

    public ExchangeRate GetExchangeRateAsync(GetRatesModel getRates)
    {
        var uriBuilder = new UriBuilder($"{CryptoExchangeUrls.BinanceApi}/api/v3/depth")
        {
            Query = $"limit=10&symbol={getRates.BaseCurrency.ToUpper()}{getRates.QuoteCurrency.ToUpper()}"
        };

        using var client = new HttpClient();

        HttpResponseMessage response = client.GetAsync(uriBuilder.Uri).Result;

        if (!response.IsSuccessStatusCode)
        {
            throw new Exception($"HTTP request failed with status code {response.StatusCode}");
        }

        OrderBookResponse deserializedResponse = response.Content.ReadFromJsonAsync<OrderBookResponse>().Result;

        ExchangeRate exchangeRate = new ExchangeRate()
        {
            ExchangeName = "Binance",
            Rate = PriceHelper.GetAveragePrice(deserializedResponse.Data)
        };

        return exchangeRate;
    }

我正在使用这个端点:

https://api.kucoin.com/api/v1/market/orderbook/level2_20?symbol=BTC-USDT
https://api.binance.com/api/v3/depth?limit=10&symbol=BTCUSDT

asp.net .net api cryptography
1个回答
0
投票

您可以使用模板函数来尝试将响应字符串反序列化为对象。有了这样的模型:

public class GenericApiResponse
{
    public HttpStatusCode StatusCode { get; set; }
    public string Content { get; set; }
}

您可以使用非常通用的功能,例如

public async Task<GenericApiResponse> ExecuteRequest(MethodEnum method, string resource, AuthModel authType,
        object body = null, Dictionary<string, string> queryParams = null, Dictionary<string, string> headers = null)
    {
        Method requestMethod = MethodEnumExtensions.ToHttpMethod(method);
        var request = new RestRequest(resource, requestMethod);
        
        if (authType.Authenticate)
        {
            request.AddHeader("Authorization", $"{authType.TokenType} {_authToken}");
        }
        
        if (body != null)
        {
            request.AddJsonBody(body);
        }

        if (queryParams != null)
        {
            foreach (var param in queryParams)
            {
                request.AddQueryParameter(param.Key, param.Value);
            }
        }

        if (headers != null)
        {
            foreach (var header in headers)
            {
                request.AddHeader(header.Key, header.Value);
            }
        }

        var response = await _client.ExecuteAsync(request);

        if (!response.IsSuccessStatusCode)
        {
            _logger.LogError($"Received error status code for request {resource}, code: {response.StatusCode}, message: {response.Content ?? "NO MESSAGE"}");
        }

        return new GenericApiResponse
        {
            Content = response.Content,
            StatusCode = response.StatusCode
        };
    }

然后使该函数适用于任何对象

public async Task<TResponse> ExecuteRequest<TResponse>(MethodEnum method, string resource, AuthModel authType,
        object body = null, Dictionary<string, string> queryParams = null, Dictionary<string, string> headers = null)
    {
        var response = await ExecuteRequest(method, resource, authType, body, queryParams, headers);

        if (response == null || response.Content == null)
        {
            _logger.LogError("Received null response");

            return default(TResponse);
        }

        TResponse result;
        try
        {
            result = JsonConvert.DeserializeObject<TResponse>(response.Content);
        }
        catch (Exception ex) 
        {
            result = JsonConvert.DeserializeObject<TResponse>(JsonConvert.SerializeObject(response.Content));
        }

        return result;
    }
© www.soinside.com 2019 - 2024. All rights reserved.