如果您正在阅读本文,那么您很可能已经知道JSON是什么,并且您熟悉下面的图片。 但是无论如何,我建议您访问此
页面(如果您以前从未到过此
页面) ,并且在阅读之前,建议您熟悉一下在C#中使用JSON表示法的一般原理,例如,
在此链接 。
我想指出的是,本说明并不伪装成对该主题的任何完整披露。 本文的目的是构造和保留我在使用Newtonsoft.Json库时使用的那些开发。问题陈述
总的来说,在本文的框架内,如何获取原始数据进行解析并不是很重要,但是,这种解释肯定会促进对材料的理解。 因此,主要任务是实现
EXMO cryptoexchange API的功能。 为简单起见,我们将主要使用公共接口(Public API)。 在这种情况下,信息请求将看起来像站点的常规页面地址。 要发送请求,请使用System.Net.Http命名空间的HttpClient类:
HttpClient httpClient = new HttpClient(); string request = "https://api.exmo.com/v1/trades/?pair=BTC_USD"; HttpResponseMessage response = (await httpClient.GetAsync(request)).EnsureSuccessStatusCode(); string responseBody = await response.Content.ReadAsStringAsync();
通过单击链接
https://api.exmo.com/v1/trades/?pair=BTC_USD可以查看该程序的结果。 如果将这些数据加载到
JSON C#Class Generator中 ,将为反序列化提供以下类结构:
public class BTCUSD { public int trade_id { get; set; } public string type { get; set; } public string quantity { get; set; } public string price { get; set; } public string amount { get; set; } public int date { get; set; } } public class RootObject { public List<BTCUSD> BTC_USD { get; set; } }
应该注意的是,加密交换“交易”功能本身允许您一次请求有关多个货币对的信息。 并且在要求的情况下
string request = "https://api.exmo.com/v1/trades/?pair=BTC_USD,ETH_USD";
类的结构已经看起来像这样:
public class BTCUSD { public int trade_id { get; set; } public string type { get; set; } public string quantity { get; set; } public string price { get; set; } public string amount { get; set; } public int date { get; set; } } public class ETHUSD { public int trade_id { get; set; } public string type { get; set; } public string quantity { get; set; } public string price { get; set; } public string amount { get; set; } public int date { get; set; } } public class RootObject { public List<BTCUSD> BTC_USD { get; set; } public List<ETHUSD> ETH_USD { get; set; } }
显然,您无法为每种货币对组合准备课程,这意味着您需要以某种方式摆脱困境。
不必这样做。令人惊讶的是,几乎不可能在俄语互联网上找到有关使用JSON表示法的优秀文章。 结果,可以在GitHub上找到的那些EXMO API实现以某种方式包含使用split,trim等等对原始数据结构的操作。
我必须承认,我还首先发明了自行车并自行实现了解析。 尽管代码绝对有效,但这是您无法执行此操作的一个很好的示例。
LinkedList<OrderInform> loi = new LinkedList<OrderInform>(); try { string[] json = answer.Split(new char[] { '{', '}' }); foreach (var item in json) { if (item.Length > 20) { string[] trade = item.Split(new char[] { ',' }); if (trade.Length > 5) { string t_id = trade[0].Split(new char[] { ':' })[1].Trim('"'); string t_type = trade[1].Split(new char[] { ':' })[1].Trim('"'); string t_quantity = trade[2].Split(new char[] { ':' })[1].Trim('"') .Replace(".", ","); string t_price = trade[3].Split(new char[] { ':' })[1].Trim('"') .Replace(".", ","); string t_amount = trade[4].Split(new char[] { ':' })[1].Trim('"') .Replace(".", ","); string t_date_time = trade[5].Split(new char[] { ':' })[1].Trim('"'); loi.AddLast(new OrderInform(pair, Convert.ToInt32(t_id), t_type, Convert.ToDouble(t_quantity), Convert.ToDouble(t_price), Convert.ToDouble(t_amount), (new DateTime(1970, 1, 1, 0, 0, 0, 0)) .AddSeconds(Convert.ToInt32(t_date_time)))); } } } return loi; } catch (Exception ex) { return new LinkedList<OrderInform>(); }
JSON对象(JObject类)
JSON对象是键/值对的无序集合。 对象以“ {”(大括号的开头)开始,以“}”(大括号的结尾)结束。 每个名称后跟:(冒号),键/值对之间用逗号分隔。

从JSON C#类生成器先前向我们提出的结构中,我们看到,对于每个货币对,我们都有6个常量字段。 将它们包装在单独的类中,并将其命名为Order。
class Order { public int trade_id { get; set; } public string type { get; set; } public double quantity { get; set; } public double price { get; set; } public double amount { get; set; } public int date { get; set; } }
为了能够从交换的动态变化的数据结构中“抓住”这些字段的集合,您需要更详细地了解newtosoft.json库中可用的数据类型。 更具体地说,在newtonsoft.json.linq命名空间中。
要使用该库,必须先安装它。要在Visual Studio中安装该库,您只需搜索NuGet。
在解决方案资源管理器中右键单击解决方案,然后选择“管理解决方案的NuGet软件包...”(管理解决方案的NuGet软件包...“)。

接下来,单击“浏览”,然后在搜索栏中输入newtosoft.json。 我们在解决方案前打勾,然后单击“安装”(“安装”)。

安装库之后,newtosoft.json.linq命名空间可用于连接到项目:
using Newtonsoft.Json.Linq;
Newtosoft.json.linq使用抽象的
JToken类表示数据,从中
继承JValue (表示简单值)和
JContainer (表示结构)类。 反过来,结构可以是
JArray (数组),
JConstructor (构造函数),
JObject (对象)或
JProperty (属性)。
JArray和JObject类具有Parse方法,该方法使您可以将JSON数据从常规字符串转换为相应的对象。 因此,如果我们对Exmo trades函数的数据结构使用JObject.Parse(String)方法:
HttpClient httpClient = new HttpClient(); string request = "https://api.exmo.com/v1/trades/?pair=BTC_USD,ETH_USD"; HttpResponseMessage response = (await httpClient.GetAsync(request)).EnsureSuccessStatusCode(); string responseBody = await response.Content.ReadAsStringAsync(); JObject jObject = JObject.Parse(responseBody);
我们将看到两个元素的结构,每个元素代表一个键值对。 在这种情况下,键将是货币对的名称(字符串类型),值将是交易清单(JToken类型):

现在,可以通过键“ BTC_USD”和“ USD_ETH”使用交易列表。 例如,使用货币对“ BTC_USD”进行的交易:

然后,我们只需要将数据转换为便于工作的类型,例如
清单<订单> 使用ToObject <>()方法:
HttpClient httpClient = new HttpClient(); string request = "https://api.exmo.com/v1/trades/?pair=BTC_USD,ETH_USD"; HttpResponseMessage response = (await httpClient.GetAsync(request)).EnsureSuccessStatusCode(); string responseBody = await response.Content.ReadAsStringAsync(); JObject jObject = JObject.Parse(responseBody); JToken list = jObject["BTC_USD"]; List<Order> trades = list.ToObject<List<Order>>();
要么将整个结构转换为类型
字典<string,列表<Order >> :
HttpClient httpClient = new HttpClient(); string request = "https://api.exmo.com/v1/trades/?pair=BTC_USD,ETH_USD"; HttpResponseMessage response = (await httpClient.GetAsync(request)).EnsureSuccessStatusCode(); string responseBody = await response.Content.ReadAsStringAsync(); JObject jObject = JObject.Parse(responseBody); Dictionary<string, List<Order>> trades = new Dictionary<string, List<Order>>(); foreach (KeyValuePair<string, JToken> obj in jObject) trades.Add(obj.Key, obj.Value.ToObject<List<Order>>());
JSON数组(JArray类)
JSON数组是值的有序集合。 数组以“ [”(方括号)开始,以“]”(方括号)结束。 值用逗号分隔。
通过点击链接
https://api.exmo.com/v1/currency可以看到JSON数组的样子。 如果您尝试将其转换为JObject,就像我们对上一个请求所做的那样:
HttpClient httpClient = new HttpClient(); string request = "https://api.exmo.com/v1/currency"; HttpResponseMessage response = (await httpClient.GetAsync(request)).EnsureSuccessStatusCode(); string responseBody = await response.Content.ReadAsStringAsync(); JObject jObject = JObject.Parse(responseBody);
我们将得到一个Newtonsoft.Json.JsonReaderException异常,告诉我们正在转换的数据不是对象。

数组必须转换为特殊的JArray类型,就像JObject一样,它是从JContainer继承的。
HttpClient httpClient = new HttpClient(); string request = "https://api.exmo.com/v1/currency"; HttpResponseMessage response = (await httpClient.GetAsync(request)).EnsureSuccessStatusCode(); string responseBody = await response.Content.ReadAsStringAsync(); JObject jObject = JObject.Parse(responseBody); JArray jArray = JArray.Parse(responseBody);
在解析的情况下,事先不知道初始结构,或者需要具有处理两种类型的数据的能力-您可以将JContainer或JToken指定为转换后的对象的类型,然后在解析期间,数据将隐式转换为所需的类型。
HttpClient httpClient = new HttpClient(); string request = "https://api.exmo.com/v1/currency"; HttpResponseMessage response = (await httpClient.GetAsync(request)).EnsureSuccessStatusCode(); string responseBody = await response.Content.ReadAsStringAsync(); JToken jArray = JToken.Parse(responseBody );
JSON值(JValue类)
根据JSON格式描述,该值可以是双引号字符串,数字,true,false,null,
对象或
数组 。 这些结构可以嵌套。 在newotnsoft.json的实现中,仅简单类型的对象可以是一个值。 尝试将JArray转换为JValue将导致“ System.InvalidCastException”异常。
作为newtonsoft.json库中使用特定值(JValue类)的入门资料,文档
一 两次的示例非常适合。
来自交易所的数据的用法示例:
HttpClient httpClient = new HttpClient(); string request = "https://api.exmo.com/v1/currency"; HttpResponseMessage response = (await httpClient.GetAsync(request)).EnsureSuccessStatusCode(); string responseBody = await response.Content.ReadAsStringAsync(); JArray jArray = JArray.Parse(responseBody ); foreach (JValue value in jArray) { string s = (string)value; }
在本文的第二部分,我将更详细地描述准备用于解析数据的类的可能性,以及使用DateTime数据类型的一些功能。
程序的全文。 using System.Threading.Tasks; using System.Collections.Generic; using System.Net.Http; using Newtonsoft.Json.Linq; namespace JSONObjects { class Order { public int trade_id { get; set; } public string type { get; set; } public double quantity { get; set; } public double price { get; set; } public double amount { get; set; } public int date { get; set; } } class Program { public static async Task Main(string[] args) { HttpClient httpClient = new HttpClient(); string request = "https://api.exmo.com/v1/currency"; HttpResponseMessage response = (await httpClient.GetAsync(request)).EnsureSuccessStatusCode(); string responseBody = await response.Content.ReadAsStringAsync(); JToken jArray = JToken.Parse(responseBody);
有关该库的最完整,最详细的信息始终可以在
官方文档中找到。