【问题标题】:Create a tree node when serializing data序列化数据时创建树节点
【发布时间】:2021-11-06 22:54:15
【问题描述】:

我从 SQL 数据库中查询了一些数据,我使用此代码对它们进行序列化:

List<Dictionary<string, object>> rows = new List<Dictionary<string, object>>();
DataTable dt = new DataTable();
...

SqlDataAdapter adapt = new SqlDataAdapter();
adapt.Fill(dt);

Dictionary<string, object> row;
foreach (DataRow dr in dt.Rows)
{
    row = new Dictionary<string, object>();
    foreach (DataColumn col in dt.Columns)
    {
        row.Add(col.ColumnName, dr[col]);
    }
    rows.Add(row);
}
return JsonSerializer.Serialize(rows);

当我序列化它们时它给了我这个结果:

{
    "operator": "Unknown",
    "extrainfo": "potential client",
    "Name": "John Doe",
    "ID": 568910,
    "LastUpdate": "2021-07-22T00:00:00",      
    "Interested?": "Yes",
    "Does it have a valid contract?": "No",
    "Contract type": "Prepaid",
    "Client willing to pay more?": "Yes, up to 20%",       
    "Comments": {}
}

我希望 lastUpdate 列之后的所有数据在另一个节点内序列化,该节点简称为 interview。 以下是我想要序列化它们的方式:

{
    "operator": "Unknown",
    "extrainfo": "potential client",
    "Name": "John Doe",
    "ID": 568910,
    "LastUpdate": "2021-07-22T00:00:00",          
    "interview": [
        {
            "question" : "Interested?",
            "answer": "Yes"
        },
        {
            "question" : "Does it have a valid contract?",
            "answer": "No"
        },
        {
            "question" : "Contract type",
            "answer": "Prepaid"
        },
        {
            "question" : "Client willing to pay more?",
            "answer": "Yes, up to 20%"
        },           
        {
            "question" : "Comments",
            "answer": ""
        }
    ]
}

这是数据库行的样子:

我想要一些关于如何做到这一点的帮助。

【问题讨论】:

    标签: c# serialization deserialization jsonserializer


    【解决方案1】:

    lastUpdate 列之后的所有数据都将在另一个节点中序列化

    之后是相对的:

    • 您的 DataTable 可能以不同的顺序定义列,然后它们应该出现在 json 中
    • 序列化程序可能使用与数据库架构不同的顺序

    过滤

    我会建议一种方法,您可以将那些应序列化为属性的字段列出,并将其余字段视为interview 问答对。

    var propertyFields = new[] { "operator", "extrainfo", "Name", "ID", "LastUpdate" };
    

    采集数据

    为了创建所需的输出(对于interview),您可能需要引入classstruct我已经介绍了named ValueTuple 以避免创建此类。但取决于您的运行时环境,它可能可用也可能不可用。 更新:ValueTuples are not supported by System.Text.Json.JsonSerializer

    struct Interview
    {
        [JsonPropertyName("question")]
        public string Question { get; set; }
        [JsonPropertyName("answer")]
        public string Answer { get; set; }
    }
    

    接线

    让我们把所有的东西放在一起

    static readonly string[] propertyFields = new[] { "operator", "extrainfo", "Name", "ID", "LastUpdate" };
    
    ...
    Dictionary<string, object> row;
    foreach (DataRow dr in dt.Rows)
    {
        row = new Dictionary<string, object>();
        var interview = new List<Interview>();
    
        foreach (DataColumn col in dt.Columns)
        {
            string name = col.ColumnName;
            object value = dr[col];
            if (propertyFields.Contains(col.ColumnName))
                row.Add(name, value);
            else
                interview.Add(new Interview { Question = name, Answer = value.ToString() });
    
        }
        row.Add("interview", interview);
        rows.Add(row);
    }
    

    【讨论】:

    • 谢谢,我以前自己找过解决办法,但是你的代码效果更好,更稳定。
    【解决方案2】:

    【讨论】:

    • 不应发布或投票赞成“仅链接的答案”。该链接可能会导致此答案无用!建议将链接中的重要部分复制到答案中并相应地对其进行结构化,以便为问题提供可行的解决方案。这将超过链接
    • 请编辑您的帖子,否则迟早会被标记:)
    【解决方案3】:

    我用元组列表替换了 sql 数据。出于算法的目的,它将是相同的。

    请注意,最简单的方法是创建一个 POCO 类来使用嵌套的“inteview”POCO 保存实际值。如果这是来自 SQL,那么您应该知道列结构。

    给出您的问题,我将假设无论出于何种原因这是不可能的,并且您不提前知道列结构并且您正在执行此操作。

    在这种情况下,您最好不要使用任何 POCO 类(包括您当前使用的字典),而只需将数据写为 JSON。一种方法如下:

        static List<(string name, string[] values)> Data = new()
        {
            ("operator", new[] { "Unknown" } ),
            ("extrainfo", new[] { "potential client" }),
            ("Name", new[] { "John Doe" }),
            ("ID", new[] { "568910" }),
            ("LastUpdate", new[] { "2021-07-22T00:00:00" }),
            ("Interested?", new[] { "Yes" } ),
            ("Does it have a valid contract?", new[] { "No" } ),
            ("Contract type", new[] { "Prepaid" } ),
            ("Client willing to pay more?", new[] { "Yes, up to 20%" } ),
            ("Comments", new string[] { }),
        };
    
        static string Serilize(List<(string name, string[] values)> data)
        {
            using var output = new MemoryStream();
            using (var writer = new Utf8JsonWriter(output, new JsonWriterOptions() { Indented = true }))
            {
                bool foundQA = false;
    
                writer.WriteStartObject();
    
                foreach (var row in data)
                {
                    if (!foundQA)
                    {
                        foreach (var value in row.values)
                        {
                            writer.WritePropertyName(row.name);
    
                            if (null != value)
                                writer.WriteStringValue(value);
                            else
                                writer.WriteStringValue("");
                        }
    
                        if (row.name == "LastUpdate")
                        {
                            writer.WritePropertyName("interview");
                            writer.WriteStartArray();
                            foundQA = true;
                        }
                    }
                    else
                    {
                        writer.WriteStartObject();
    
                        writer.WritePropertyName("question");
                        writer.WriteStringValue(row.name);
    
                        writer.WritePropertyName("answer");
                        writer.WriteStringValue(row.values.Length > 0 ? row.values[0] : "");
    
                        writer.WriteEndObject();
                    }
                }
    
                if (foundQA)
                {
                    writer.WriteEndArray();
                }
    
                writer.WriteEndObject();
            }
    
            return Encoding.UTF8.GetString(output.ToArray());
        }
    
    
        static void Main(string[] args)
        {
            string formattedJson = Serilize(Data);
    
            Console.WriteLine("Formatted output:");
            Console.WriteLine(formattedJson);
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多