簡體   English   中英

從 C# 中的嵌套字典生成 JSON

[英]Generating JSON from nested Dictionary in C#

我有以下字典:

Dictionary<string, Dictionary<string, List<ChartData>>> data;

ChartData 實現如下所示:

   public struct ChartData
    {
        public long datetime;
        public double open;
        public double high;
        public double low;
        public double close;
        public ulong tick_volume;
        public int spread;
        public ulong volume;
    }

我想使用數據容器中的數據生成 JSON。 我的數據必須看起來像這樣:

{
    "EURUSD": [
        {
            "PROV": [
                {
                    "datetime":34534554,
                    "open":2.31,
                    "high":123,
                    "low":3213,
                    "close":213,
                    "tick_volume":2131,
                    "spread":2131,
                    "volume":3123
                },
                {
                    "datetime":34534554,
                    "open":2.31,
                    "high":123,
                    "low":3213,
                    "close":213,
                    "tick_volume":2131,
                    "spread":2131,
                    "volume":3123
                }
            ],
            "LMAX":[
                {
                    "datetime":34534554,
                    "open":2.31,
                    "high":123,
                    "low":3213,
                    "close":213,
                    "tick_volume":2131,
                    "spread":2131,
                    "volume":3123
                }
            ]
        }
    ],
    "BTCUSD":[
        {
            "PROV":[
                {
                    "datetime":34534554,
                    "open":2.31,
                    "high":123,
                    "low":3213,
                    "close":213,
                    "tick_volume":2131,
                    "spread":2131,
                    "volume":3123
                }
            ]
        }
    ]
}

我現在的解決方案是這樣的:

   var jsonObjectData= JObject.Parse(System.Text.Json.JsonSerializer.Serialize(data));
    var result = new JObject();

    result.Merge(jsonObjectData);

    var json = result.ToString(Newtonsoft.Json.Formatting.Indented);

但我在這里沒有看到任何正確的數據。

您有什么建議可以用來從我的嵌套字典容器中生成所需的 JSON 嗎?

我將不勝感激任何幫助。

嘗試使用 newtonsoft:

string output = JsonConvert.SerializeObject(data);

這里的主要問題是默認情況下System.Text.Json.Serializer不會序列化字段。 Amjad 的解決方案之所以有效,是因為 NewtonSoft 默認會序列化所有字段和屬性,只要它們是public

對此的最佳實踐建議是更改您的 model以便ChartData使用屬性而不是字段

public struct ChartData
{
    public long datetime { get;set; }
    public double open { get;set; }
    public double high { get;set; }
    public double low { get;set; }
    public double close { get;set; }
    public ulong tick_volume { get;set; }
    public int spread { get;set; }
    public ulong volume { get;set; }
}

或者,如果您不想使用屬性,可以使用[JsonInclude]屬性注釋字段

public struct ChartData
{
    [System.Text.Json.Serialization.JsonInclude]
    public long datetime;
    [System.Text.Json.Serialization.JsonInclude]
    public double open;
    [System.Text.Json.Serialization.JsonInclude]
    public double high;
    [System.Text.Json.Serialization.JsonInclude]
    public double low;
    [System.Text.Json.Serialization.JsonInclude]
    public double close;
    [System.Text.Json.Serialization.JsonInclude]
    public ulong tick_volume;
    [System.Text.Json.Serialization.JsonInclude]
    public int spread;
    [System.Text.Json.Serialization.JsonInclude]
    public ulong volume;
}

ChartData結構的任何更改都將包含此代碼的 output 中的內容:

string json = System.Text.Json.JsonSerializer.Serialize(data);

還有另一種選擇,但它被廣泛認為是一種Anti-Pattern ,即在選項中指定要包含字段的選項:

var options = new System.Text.Json.JsonSerializerOptions  
              { 
                  WriteIndented = true,
                  IncludeFields = true  
              };
string json = System.Text.Json.JsonSerializer.Serialize(data, options);

IncludeFields設置是此特定場景的簡單選項,因為它不需要更改 model,但這樣做將包括正在序列化的所有嵌套對象的字段,而不僅僅是ChartData 這可能會導致包含意外內容。 我們建議在.Net 中使用public屬性而不是字段,反之亦然,在 class 設計中,我們希望字段不會包含在序列化 output 中。

.NET 社區充分理解並接受了這方面的原因和理由,因此我不會在這里詳細介紹 go,但重要的是再次強調您應該尊重與屬性字段相關的預期行為,這就是為什么您應該使用屬性或專門注釋您的字段以聲明您希望將值包含在序列化 output 中。

您不想養成在所有序列化例程中使用IncludeFields選項的習慣,因為不同的數據類型可能表現出非常不同的輸出,這甚至可能影響反序列化過程。


As Amjab Saab has posted you could also use Newtonsoft's Newtonsoft's Json.NET instead of System.Text.Json however in this case the .NET team are specifically guiding us to design our classes better and are actively trying to enforce code standards and declarative design patterns, where Newtonsoft's方法是不可知地適應不同的設計模式。 因此,.NET 的實現速度明顯更快,我鼓勵您繼續使用System.Text.Json

請注意, Netwonsoft.Json的作者 James Newton-King 是負責System.Text.Json團隊的關鍵工程師。 將 System.Text.Json 視為一種演變,它特別具有性能和符合 JSON 規范作為關鍵目標。 在此處閱讀更多內容: Newtonsoft.Json 和 System.Text.Json 之間的簡要比較

我准備了一個小提琴,展示了兩個庫之間的一個區別: https://dotnetfiddle.net/MSO1iA

結果使用 System.Text.Json.JsonSerializer.Serialize(data);

{
  "EURUSD": {
    "PROV": [
      {},
      {}
    ],
    "LMAX": [
      {}
    ]
  },
  "BTCUSD": {
    "PROV": [
      {}
    ]
  }
}

結果使用 System.Text.Json.JsonSerializer.Serialize(data, new JsonSerializerOptions { IncludeFields = true });

{
  "EURUSD": {
    "PROV": [
      {
        "datetime": 34534554,
        "open": 2.31,
        "high": 123,
        "low": 213,
        "close": 213,
        "tick_volume": 2131,
        "spread": 2131,
        "volume": 3123
      },
      {
        "datetime": 34534554,
        "open": 2.31,
        "high": 123,
        "low": 3213,
        "close": 213,
        "tick_volume": 2131,
        "spread": 2131,
        "volume": 3123
      }
    ],
    "LMAX": [
      {
        "datetime": 34534554,
        "open": 2.31,
        "high": 123,
        "low": 3213,
        "close": 213,
        "tick_volume": 2131,
        "spread": 2131,
        "volume": 3123
      }
    ]
  },
  "BTCUSD": {
    "PROV": [
      {
        "datetime": 34534554,
        "open": 2.31,
        "high": 123,
        "low": 3213,
        "close": 213,
        "tick_volume": 2131,
        "spread": 2131,
        "volume": 3123
      }
    ]
  }
}

結果使用 Newtonsoft.Json.JsonConvert.SerializeObject(data);

這包含在與剛剛接觸當前版本的.Net 的開發人員的比較中

{
  "EURUSD": {
    "PROV": [
      {
        "datetime": 34534554,
        "open": 2.31,
        "high": 123.0,
        "low": 213.0,
        "close": 213.0,
        "tick_volume": 2131,
        "spread": 2131,
        "volume": 3123
      },
      {
        "datetime": 34534554,
        "open": 2.31,
        "high": 123.0,
        "low": 3213.0,
        "close": 213.0,
        "tick_volume": 2131,
        "spread": 2131,
        "volume": 3123
      }
    ],
    "LMAX": [
      {
        "datetime": 34534554,
        "open": 2.31,
        "high": 123.0,
        "low": 3213.0,
        "close": 213.0,
        "tick_volume": 2131,
        "spread": 2131,
        "volume": 3123
      }
    ]
  },
  "BTCUSD": {
    "PROV": [
      {
        "datetime": 34534554,
        "open": 2.31,
        "high": 123.0,
        "low": 3213.0,
        "close": 213.0,
        "tick_volume": 2131,
        "spread": 2131,
        "volume": 3123
      }
    ]
  }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM