简体   繁体   English

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

[英]Generating JSON from nested Dictionary in C#

I have the following Dictionary:我有以下字典:

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

ChartData implementation looks like this: 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;
    }

I want to generate JSON using the data I have in my data container.我想使用数据容器中的数据生成 JSON。 My data must look something like that:我的数据必须看起来像这样:

{
    "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
                }
            ]
        }
    ]
}

The solution I have right now is this:我现在的解决方案是这样的:

   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);

But I don't see any correct data here.但我在这里没有看到任何正确的数据。

Do you have any suggestions, that I could use to generate the required JSON from my nested Dictionary container?您有什么建议可以用来从我的嵌套字典容器中生成所需的 JSON 吗?

I would appreciate any help.我将不胜感激任何帮助。

Try using newtonsoft:尝试使用 newtonsoft:

string output = JsonConvert.SerializeObject(data);

The major issue here is that by default, System.Text.Json.Serializer will NOT serialize fields.这里的主要问题是默认情况下System.Text.Json.Serializer不会序列化字段。 The solution from Amjad works because NewtonSoft serializes all fields and properties by default, as long as they are public . Amjad 的解决方案之所以有效,是因为 NewtonSoft 默认会序列化所有字段和属性,只要它们是public

The best practice advice for this is to change your model so that ChartData uses properties instead of fields :对此的最佳实践建议是更改您的 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; }
}

Alternatively, if you do not want to use properties you can annotate the fields with the [JsonInclude] Attribute:或者,如果您不想使用属性,可以使用[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;
}

Either of those changes to the ChartData struct will include the content in the output of this code:ChartData结构的任何更改都将包含此代码的 output 中的内容:

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

There is another option, but it is widely considered an Anti-Pattern , that is to specify in the options that you want to include fields as well:还有另一种选择,但它被广泛认为是一种Anti-Pattern ,即在选项中指定要包含字段的选项:

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

The IncludeFields setting is the easy option for this particular scenario as it doesn't require changes to the model, but doing this will include the fields of ALL nested objects that are being serialized, not just ChartData . IncludeFields设置是此特定场景的简单选项,因为它不需要更改 model,但这样做将包括正在序列化的所有嵌套对象的字段,而不仅仅是ChartData This can lead to unexpected content being included.这可能会导致包含意外内容。 We recommend in.Net that you use public properties instead of fields , the reverse is also true, in class design, we expect that fields WILL NOT be included in serilization output.我们建议在.Net 中使用public属性而不是字段,反之亦然,在 class 设计中,我们希望字段不会包含在序列化 output 中。

The reasons and justifications on this are well understood and accepted by the .NET community so I won't go into detail here, but it is important to highlight again that you should respect the expected behaviours associated with properties and fields and that is why you should use properties or specifically annotate your fields to declare that you want the values to be included in serialization output. .NET 社区充分理解并接受了这方面的原因和理由,因此我不会在这里详细介绍 go,但重要的是再次强调您应该尊重与属性字段相关的预期行为,这就是为什么您应该使用属性或专门注释您的字段以声明您希望将值包含在序列化 output 中。

You do not want to get into the habit of using the IncludeFields option in all of your serialization routines, as different data type may exhibit very different outputs and this may even affect deserialization processes.您不想养成在所有序列化例程中使用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 approach is to be resilient to different design patterns agnostically. 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方法是不可知地适应不同的设计模式。 Due to this the .NET implementation is significantly faster and I encourage you to continue using System.Text.Json .因此,.NET 的实现速度明显更快,我鼓励您继续使用System.Text.Json

Note that James Newton-King, the author of Netwonsoft.Json is a key engineer in the team responsible for System.Text.Json .请注意, Netwonsoft.Json的作者 James Newton-King 是负责System.Text.Json团队的关键工程师。 Think of System.Text.Json as an evolution that specifically has performance and conformance to JSON specification as a key goals.将 System.Text.Json 视为一种演变,它特别具有性能和符合 JSON 规范作为关键目标。 read more here: A Brief Comparison Between Newtonsoft.Json and System.Text.Json在此处阅读更多内容: Newtonsoft.Json 和 System.Text.Json 之间的简要比较

I have prepared a fiddle showing one difference between the two libraries: https://dotnetfiddle.net/MSO1iA我准备了一个小提琴,展示了两个库之间的一个区别: https://dotnetfiddle.net/MSO1iA

Result using System.Text.Json.JsonSerializer.Serialize(data);结果使用 System.Text.Json.JsonSerializer.Serialize(data);

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

Result using System.Text.Json.JsonSerializer.Serialize(data, new JsonSerializerOptions { IncludeFields = true });结果使用 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
      }
    ]
  }
}

Result using Newtonsoft.Json.JsonConvert.SerializeObject(data);结果使用 Newtonsoft.Json.JsonConvert.SerializeObject(data);

This is included as a comparison for devs who are just coming across to the current versions of.Net这包含在与刚刚接触当前版本的.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