首页 > 解决方案 > 如何在不知道 JSON 值的情况下动态解析一些 JSON?

问题描述

所以我使用 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 中进行搜索,就好像它都是一堆数组一样?

标签: c#jsonapijson-deserialization

解决方案


这是您尝试使用的 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

该方法的签名是这样的: public static Object DeserializeObject(string value)

参数为:json字符串类型的值。

返回值为:对象类型的对象。


如果您不想要对象,那么您当然可以使用您拥有的 .Net 类型。比如这个方法:JsonConvert.DeserializeObject Method(String)

您在两者中拥有的任何属性(.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();
            }
        }
    }  
}

推荐阅读