首页 > 解决方案 > 使用 Json.net 反序列化具有一些更改对象名称的 Json

问题描述

我是新来的,所以感谢您提供的精彩内容;无价之宝。

我正在使用“选项链”api 将 TDAmeritrade 中的一些 Json 反序列化为 C# 桌面应用程序。

根据 api 的输入,我可以获得包含多个到期日期、多个执行价格和多个期权对象的响应。

这是典型响应的链接:API ResponseTDAmeritrade Json Example

问题代码片段:

"numberOfContracts": 8,
  "putExpDateMap": {

    **"2020-08-21:50": {
      "15.0":** [

        {
          "putCall": "PUT",
          "symbol": "FMCI_082120P15",
          "description": "FMCI Aug 21 2020 15 Put",
          "exchangeName": "OPR",

问题是每个响应中的日期和执行价格都会发生变化。我了解到我可以反序列化为“Dictionary<string, List<Type> listName”,所以我在 OptionChain 和 ExpDate 类中做到了这一点,但仍然无法让它工作。

这是当前错误:错误跟踪

这是我的类,从 json2csharp.com 创建,但修改了日期和执行价格类:

 class OptionChain
{
    public string symbol { get; set; }
    public string status { get; set; }
    public Underlying underlying { get; set; }
    public string strategy { get; set; }
    public double interval { get; set; }
    public bool isDelayed { get; set; }
    public bool isIndex { get; set; }
    public double interestRate { get; set; }
    public double underlyingPrice { get; set; }
    public double volatility { get; set; }
    public double daysToExpiration { get; set; }
    public int numberOfContracts { get; set; }   
    public Dictionary<string, List<expDate>> putExpDateMap { get; set; }
    public Dictionary<string, List<expDate>> callExpDateMap { get; set; }

public class expDate
{
    public Dictionary<string, List<StrikePrice>> strikePrices { get; set; }
}

public class StrikePrice
{
    public Option[] options { get; set; }
}

public class Option
{
    public string putCall { get; set; }
    public string symbol { get; set; }
    public string description { get; set; }
    public string exchangeName { get; set; }
    public double bid { get; set; }
    public double ask { get; set; }
    public double last { get; set; }
    public double mark { get; set; }
    public int bidSize { get; set; }
    public int askSize { get; set; }
    public string bidAskSize { get; set; }
    public int lastSize { get; set; }
    public double highPrice { get; set; }
    public double lowPrice { get; set; }
    public double openPrice { get; set; }
    public double closePrice { get; set; }
    public int totalVolume { get; set; }
    public object tradeDate { get; set; }
    public long tradeTimeInLong { get; set; }
    public long quoteTimeInLong { get; set; }
    public double netChange { get; set; }
    public double volatility { get; set; }
    public double delta { get; set; }
    public double gamma { get; set; }
    public double theta { get; set; }
    public double vega { get; set; }
    public double rho { get; set; }
    public int openInterest { get; set; }
    public double timeValue { get; set; }
    public double theoreticalOptionValue { get; set; }
    public double theoreticalVolatility { get; set; }
    public  OptionDeliverablesList optionDeliverablesList { get; set; }
    public double strikePrice { get; set; }
    public long expirationDate { get; set; }
    public int daysToExpiration { get; set; }
    public string expirationType { get; set; }
    public long lastTradingDay { get; set; }
    public double multiplier { get; set; }
    public string settlementType { get; set; }
    public string deliverableNote { get; set; }
    public bool isIndexOption { get; set; }
    public double percentChange { get; set; }
    public double markChange { get; set; }
    public double markPercentChange { get; set; }
    public bool inTheMoney { get; set; }
    public bool mini { get; set; }
    public bool nonStandard { get; set; }

 public class OptionDeliverablesList
{
    public string symbol { get; set; }
    public string assetType { get; set; }
    public double deliverableUnits { get; set; }
    public string currencyType { get; set; }
}

我在字典中做错了吗?我从数小时的阅读中理解它的方式,到期日期和执行价格需要匿名阅读。

非常感谢!

标签: c#serializationjson.net

解决方案


如果我的问题正确 - 你有反序列化 json 结构的问题,其中键是动态值而不是静态属性名称,对吗?如果是这样-您建模了不正确的 POCO(有两个嵌套字典)。下面的 POCO 给出了正确的反序列化结果(跳过了其余属性)

class OptionChain
{
    public string Symbol { get; set; }
    public string Status { get; set; }
    public Dictionary<string, Dictionary<string, ExpDate[]>> PutExpDateMap { get; set; }
    public Dictionary<string, Dictionary<string, ExpDate[]>> CallExpDateMap { get; set; }
    //other properties ignored because dont matter
}

class ExpDate
{
    public string ExchangeName { get; set; }
    public decimal Bid { get; set; }
    public decimal Ask { get; set; }
    //other properties ignored because dont matter
}

使用您的帖子中提供的 json 示例测试过的 POCO:

    static void Main(string[] args)
    {
        var t = File.ReadAllText("test.json");
        var r = JsonConvert.DeserializeObject<OptionChain>(t);
        Console.WriteLine($"Total elements in {nameof(r.PutExpDateMap)} : {r.PutExpDateMap.Count()}");
        Console.WriteLine($"Keys in {nameof(r.PutExpDateMap)} : {string.Join(",", r.PutExpDateMap.Keys)}");
        Console.WriteLine($"Total elements in {nameof(r.CallExpDateMap)} : {r.CallExpDateMap.Count()}");
        Console.WriteLine($"Keys in {nameof(r.CallExpDateMap)} : {string.Join(",", r.CallExpDateMap.Keys)}");
    }

应用程序输出为:

在此处输入图像描述


推荐阅读