C#:解析对具有 x 属性的类对象的非 JSON 仅数组 api 响应 [英] C#: Parsing a non-JSON array-only api response to a class object with x properties

查看:17
本文介绍了C#:解析对具有 x 属性的类对象的非 JSON 仅数组 api 响应的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我收到了一些 Rest API 的响应,它只返回一些数组,如下所示:

<预><代码>[[123,"0.01","0.02","0.03","0.04","12345.00000",123456789,"300.000",4000,"123.000","456.000","0"],[456,"0.04","0.03","0.02","0.01","54321.00000",987654321,"500.000",4000,"123.000","456.000","1"],[789,"0.05","0.06","0.07","0.08","12345.00000",123456789,"700.000",8000,"456.000","123.000","0"]]

在这个例子中,数据集的数量是 3,但数量总是不同的,也可能是 100+.

我想将其读出到一个类对象中,该对象根据响应中显示的每种类型的值有 12 个数组:

公共类foo{...public int[] firstParam;公共字符串[] secondParam;公共字符串[]第三参数;...}

例如,firstParam 应该包含 then {123,456,789};secondParam 应该包含 {"0.01","0.04","0.05"} 等等.

列的架构已知并记录在 Binance 的公共 Rest API:Kline/Candlestick 数据..一个例子是一些查询,如 https://api.binance.com/api/v1/klines?symbol=XVGBTC&interval=1h

解决方案

API 响应完全有效 JSON;它是原始值的锯齿状二维数组,其中列具有 Binance 的公共 Rest API:Kline/Candlestick 数据.因此,它可以使用 ,例如作为 object [][]:

var arrays = JsonConvert.DeserializeObject(jsonString);

(工作示例 .Net fiddle #1.)

然而,我建议您设计一个类 BinanceKlineData 表示这些特定列的单行值,然后使用 自定义 JsonConverter ObjectToArrayConverter 来自 如何将具有固定架构的值数组反序列化为强类型数据类?.

首先,使用列的文档含义,您可以定义您的类型 BinanceKlineData 如下:

公共类 BinanceKlineData{[JsonProperty(Order = 1)]公共长开放时间{得到;放;}[JsonProperty(Order = 2)]公共十进制打开{获取;放;}//或者字符串,如果你喜欢[JsonProperty(Order = 3)]公共十进制高{得到;放;}//或者字符串,如果你喜欢[JsonProperty(Order = 4)]公共十进制低{得到;放;}//或者字符串,如果你喜欢[JsonProperty(Order = 5)]公共十进制关闭{得到;放;}//或者字符串,如果你喜欢[JsonProperty(Order = 6)]公共十进制体积{得到;放;}//或者字符串,如果你喜欢[JsonProperty(Order = 7)]公共长关闭时间{得到;放;}[JsonProperty(Order = 8)]公共十进制 QuoteAssetVolume { 获取;放;}//或者字符串,如果你喜欢[JsonProperty(Order = 9)]public long NumberOfTrades { 获取;放;}//这应该是长整数还是小数?[JsonProperty(Order = 10)]公共十进制 TakerBuyBaseAssetVolume { get;放;}[JsonProperty(Order = 11)]公共十进制 TakerBuyQuoteAssetVolume { 获取;放;}//公共字符串忽略 { get;放;}}

请注意,我已使用 [JsonProperty(Order= N)].此顺序对应于 Rest API 中列的顺序,将用于通知 Json.NET 如何通过列索引将列映射到属性.另请注意,我将数字列建模为 decimal,尽管它们在 JSON 中显示为字符串.如果您更喜欢文字反序列化,可以使用 string.

接下来,从这个答案中获取通用的ObjectToArrayConverter.它具有利用 Order = N 元数据将行值映射到泛型类型 T 中按列索引的成员值的逻辑.

最后,您将能够将 JSON 反序列化为 List,如下所示:

var settings = new JsonSerializerSettings{转换器 = { new ObjectToArrayConverter() },};var root = JsonConvert.DeserializeObject>(jsonString, settings);

工作示例 .Net fiddle #2.

或者,如果您愿意,可以将转换器直接应用于 BinanceKlineData,如下所示:

[JsonConverter(typeof(ObjectToArrayConverter))]公开课 BinanceKlineData{//剩下的和之前一样}

当转换器直接应用于类型时,不再需要通过 JsonSerializerSettings.Converters 传入.

示例 小提琴 #3.

I have a response from some Rest API that just returns some array of arrays like the following:

[
[123,"0.01","0.02","0.03","0.04","12345.00000",123456789,"300.000",4000,"123.000","456.000","0"],
[456,"0.04","0.03","0.02","0.01","54321.00000",987654321,"500.000",4000,"123.000","456.000","1"],
[789,"0.05","0.06","0.07","0.08","12345.00000",123456789,"700.000",8000,"456.000","123.000","0"]    
]

In this example, the amount of datasets is 3, but the amount is always different and could be 100+ also.

I want to have this read out into a class object, which has 12 arrays according to each type of value shown in the response:

public class foo
{
    ...
    public int[] firstParam;
    public string[] secondParam;
    public string[] thirdParam;

    ...        
}

For example, firstParam should contain then {123,456,789}; secondParam should contain {"0.01","0.04","0.05"} and so on.

The schema for the columns is known and documented in Public Rest API for Binance: Kline/Candlestick data.. An example would be some query like https://api.binance.com/api/v1/klines?symbol=XVGBTC&interval=1h

解决方案

The API response is perfectly valid JSON; it is a jagged 2d array of primitive values where the columns have specific meanings as defined in the Public Rest API for Binance: Kline/Candlestick data. As such it can be parsed and deserialized using , e.g. as an object [][]:

var arrays = JsonConvert.DeserializeObject<object [][]>(jsonString);

(Sample working .Net fiddle #1.)

However, rather than deserializing the JSON into a jagged 2d object array or (as you suggest in your question) a single root object with array properties corresponding to column values, I would recommend that you design a class BinanceKlineData that represents a single row of values for those specific columns, then deserialize into a List<BinanceKlineData> using the custom JsonConverter ObjectToArrayConverter<BinanceKlineData> from How to deserialize an array of values with a fixed schema to a strongly typed data class?.

Firstly, using the documented meanings of the columns, you can define your type BinanceKlineData as follows:

public class BinanceKlineData
{
    [JsonProperty(Order = 1)]
    public long OpenTime { get; set; }
    [JsonProperty(Order = 2)]
    public decimal Open { get; set; } // Or string, if you prefer
    [JsonProperty(Order = 3)]
    public decimal High { get; set; } // Or string, if you prefer
    [JsonProperty(Order = 4)]
    public decimal Low { get; set; } // Or string, if you prefer
    [JsonProperty(Order = 5)]
    public decimal Close { get; set; } // Or string, if you prefer
    [JsonProperty(Order = 6)]
    public decimal Volume { get; set; } // Or string, if you prefer
    [JsonProperty(Order = 7)]
    public long CloseTime { get; set; }
    [JsonProperty(Order = 8)]
    public decimal QuoteAssetVolume { get; set; } // Or string, if you prefer
    [JsonProperty(Order = 9)]
    public long NumberOfTrades { get; set; } // Should this be an long or a decimal?
    [JsonProperty(Order = 10)]
    public decimal TakerBuyBaseAssetVolume { get; set; }
    [JsonProperty(Order = 11)]
    public decimal TakerBuyQuoteAssetVolume { get; set; }
    // public string Ignore { get; set; }
}

Notice that I have annotated the properties with [JsonProperty(Order = N)]. This order corresponds to the order of the columns in the Rest API, and will be used to inform Json.NET how to map columns to properties by column index. Notice also that I modeled the numeric columns as decimal despite the fact that they appear as strings in the JSON. You could use string if you prefer a more literal deserialization.

Next, grab the generic ObjectToArrayConverter<T> from this answer. It has logic to make use of the Order = N metadata to map row values to member values in the generic type T by column index.

Finally, you will be able to deserialize the JSON as a List<BinanceKlineData> as follows:

var settings = new JsonSerializerSettings
{
    Converters = { new ObjectToArrayConverter<BinanceKlineData>() },
};

var root = JsonConvert.DeserializeObject<List<BinanceKlineData>>(jsonString, settings);

Sample working .Net fiddle #2.

Or if you prefer you could apply the converter directly to BinanceKlineData as follows:

[JsonConverter(typeof(ObjectToArrayConverter<BinanceKlineData>))]
public class BinanceKlineData
{
    // Remainder as before
}

When the converter is applied directly to the type it is no longer necessary to pass it in via JsonSerializerSettings.Converters.

Sample fiddle #3.

这篇关于C#:解析对具有 x 属性的类对象的非 JSON 仅数组 api 响应的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆