问题描述
所以我使用 TdameriTrade API 在 Visual Studio 上通过 C# Winforms 程序接收股票数据。它需要用户输入股票代码并搜索信息。我正在使用 HttpClient 和 Newtonsoft.Json,并且能够成功执行 GET 请求并接收回 JSON 字符串,但我不知道如何从中获取我需要的所有信息。
这是JSON: https://drive.google.com/file/d/1TpAUwjyqrHArEXGXMof_K1eQe0hFoaw5/view?usp=sharing
上面是发回给我然后格式化的 JSON 字符串。我的目标是在“callExpDateMap.2021-02-19:11”和“callExpDateMap.2021-03-19:39”中记录每个价格的信息。问题在于,对于每种不同的股票,“callExpDateMap”中显示的日期会有所不同。
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer",token);
var response = await client.GetAsync(url);
var info = await response.Content.ReadAsstringAsync();
dynamic config = JsonConvert.DeserializeObject<dynamic>(info,new ExpandoObjectConverter());
return config;
这是我现在拥有的代码。我知道最后一个 for 语句是不正确的。我如何解析我想要的特定部分 (callExpDateMap.expirationdate.StrikePrice) 并从每个部分获取所需的信息,而无需事先知道日期和行使价?有没有办法枚举它并搜索JSON,就好像它是一堆数组一样?
解决方法
这是您尝试使用的 Newtonsoft 方法的官方文档。
https://www.newtonsoft.com/json/help/html/Overload_Newtonsoft_Json_JsonConvert_DeserializeObject.htm
如果某个 API 的方法返回不同的 json 属性,并且您不能始终相信它的属性名称,那么您可以尝试使用返回 .Net 对象的反序列化方法,例如:JsonConvert.DeserializeObject Method (String) https://www.newtonsoft.com/json/help/html/M_Newtonsoft_Json_JsonConvert_DeserializeObject.htm
该方法的签名是这样的: 公共静态对象反序列化对象(字符串值)
参数为:json字符串类型的值。
返回值为:object 类型的对象。
如果您不想要一个对象,那么您当然可以使用您拥有的 .Net 类型。比如这个方法: JsonConvert.DeserializeObject 方法(字符串)
您同时拥有的任何属性(.net 类型和 json 对象)都将被填充。如果 .net 类型具有 json 对象中不存在的属性,则这些属性将被忽略。如果 json 对象具有 .net 中不存在的属性,那么这些属性也会被忽略。
这是一个 .Net 类型的例子
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Serialization;
using System.Collections.Generic;
using System.IO;
using System.Text;
namespace MyNameSpace
{
public class TDAmeritradeStockData
{
[JsonProperty("symbol")]
public string Symbol { get; set; }
[JsonProperty("status")]
public string Status { get; set; }
[JsonProperty("callExpDateMap")]
public object CallExpDateMap { get; set; }
//...
//...
public CallExpDateMapType[] CallExpDateMapList { get; set; }
}
public class CallExpDateMapType
{
[JsonProperty("expirationdate")]
public string Expirationdate { get; set; }
[JsonProperty("StrikePrice")]
public List<StrikePriceType> StrikePriceList { get; set; }
}
public class StrikePriceType
{
public string StrikePrice { get; set; }
public List<StrikePricePropertiesType> StrikePricePropertiesList { get; set; }
}
public class StrikePricePropertiesType
{
[JsonProperty("putCall")]
public string PutCall { get; set; }
[JsonProperty("symbol")]
public string Symbol { get; set; }
[JsonProperty("description")]
public string Description { get; set; }
[JsonProperty("exchangeName")]
public string ExchangeName { get; set; }
[JsonProperty("bid")]
public double Bid { get; set; }
[JsonProperty("ask")]
public double Ask { get; set; }
//...
//...
}
[TestClass]
public class TestTestTest
{
[TestMethod]
public void JsonTest()
{
var jsondata = ReadFile("data.json");
var model = JsonConvert.DeserializeObject<TDAmeritradeStockData>(jsondata);
JObject jObject = (JObject)model.CallExpDateMap;
var count = ((JObject)model.CallExpDateMap).Count;
model.CallExpDateMapList = new CallExpDateMapType[count];
var jToken = (JToken)jObject.First;
for (var i = 0; i < count; i++)
{
model.CallExpDateMapList[i] = new CallExpDateMapType
{
Expirationdate = jToken.Path,StrikePriceList = new List<StrikePriceType>()
};
var nextStrikePrice = jToken.First.First;
while (nextStrikePrice != null)
{
var nextStrikePriceProperties = nextStrikePrice;
var srikePriceList = new StrikePriceType
{
StrikePrice = nextStrikePriceProperties.Path,StrikePricePropertiesList = JsonConvert.DeserializeObject<List<StrikePricePropertiesType>>(nextStrikePrice.First.ToString())
};
model.CallExpDateMapList[i].StrikePriceList.Add(srikePriceList);
nextStrikePrice = nextStrikePrice.Next;
}
jToken = jToken.Next;
}
Assert.IsNotNull(model);
}
private string ReadFile(string fileName)
{
using (var fileStream = new FileStream(fileName,FileMode.Open,FileAccess.Read))
{
var data = new StringBuilder();
using (var streamReader = new StreamReader(fileStream))
{
while (!streamReader.EndOfStream) data.Append(streamReader.ReadLine());
streamReader.Close();
}
fileStream.Close();
return data.ToString();
}
}
}
}
,
下面的代码可能不是最优雅也不是最完整的,但我认为它会让你继续前进。我将首先使用 JObject.Parse()
命名空间中的 Newtonsoft.Json.Linq
并从那里获取它。
JObject root = JObject.Parse(info);
string symbol = root["symbol"].ToObject<string>();
foreach (JToken toplevel in root["callExpDateMap"].Children())
{
foreach (JToken nextlevel in toplevel.Children())
{
foreach (JToken bottomlevel in nextlevel.Children())
{
foreach (JToken jToken in bottomlevel.Children())
{
JArray jArray = jToken as JArray;
foreach (var arrayElement in jArray)
{
InfoObject infoObject = arrayElement.ToObject<InfoObject>();
Console.WriteLine(infoObject.putCall);
Console.WriteLine(infoObject.exchangeName);
Console.WriteLine(infoObject.multiplier);
}
}
}
}
}
public class InfoObject
{
public string putCall { get; set; }
public string symbol { get; set; }
public string description { get; set; }
public string exchangeName { get; set; }
// ...
public int multiplier { get; set; }
// ...
}