Happy Coding Json To C# Class (Mendeleev’s periodic table)
2023-07-04
快樂的開發系列之示範如何使用 C# 處理 Json 資料,同時說明 html template 的輸出技巧。
說明
Program.cs
是本次示範的程式靈魂,主要從 GitHub 讀取元素週期表的 Json 資料。
接著透過 Json.NET 的 DeserializeObject
轉換為 C# 類別。
要進行這個動作必須先定義 C# Class,藉由選擇性貼上,將 Json 的 Schema 轉換成 C# Class,其中命名 Convention 的部分逐一調整,並且將 RootElement 換上更為適合的名稱 PeriodicTable
。
轉換成 C# 物件之後,處理就是行雲流水。目標是產出組合的字串,顯示化學元素的名稱以及化學模型,因為要重複組合字串,使用 StringBuilder
來處理。
StringBuilder 的好處包括:
效能優化:當需要連接大量字串時,使用 StringBuilder 比使用 + 或 += 連接運算符效能更好。這是因為 StringBuilder 在內部使用可調整大小的緩衝區,以減少記憶體重複配置和字串複製的次數。
避免產生多個臨時字串物件:在使用 + 或 += 連接運算符時,每次連接都會產生一個新的字串物件。對於大量連接操作,這可能會產生許多臨時的、不再使用的字串物件,佔用額外的記憶體並增加垃圾回收的負擔。而 StringBuilder 在內部緩衝區的基礎上進行操作,避免了這種額外的記憶體配置和回收。
為了增加可讀性,使用 template.html
的方式,當作 html 的 layout,並使用 使用 File.ReadAllText("template.html")
讀取;要插入的字串則結合 interpolated string 以及 verbatim string 來排版字串內容。
最後結果使用 File.WriteAllText
寫入至檔案,並搭配 Environment.GetFolderPath(Environment.SpecialFolder.Desktop)
指定是在執行環境的桌面位置 😁
Program.cs
using Newtonsoft.Json;
using System;
using System.IO;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
namespace JsonParsingExample
{
class Program
{
static async Task Main(string[] args)
{
string url = "https://raw.githubusercontent.com/Bowserinator/Periodic-Table-JSON/master/PeriodicTableJSON.json";
using (HttpClient client = new HttpClient())
{
try
{
string json = await client.GetStringAsync(url);
string desktop = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
string filePath = Path.Combine(desktop, "element.html");
string template = File.ReadAllText("template.html");
PeriodicTable periodicTable = JsonConvert.DeserializeObject<PeriodicTable>(json);
StringBuilder dataBuilder = new StringBuilder();
foreach (Element element in periodicTable.Elements)
{
string elementHtml = $@"
<div class='col-md-3 my-3'>
<ul class='list-group'>
<li class='list-group-item'>
{element.Symbol}
<img class='img-fluid' src='{element.Bohr_model_image}'/>
</li>
</ul>
</div>";
dataBuilder.Append(elementHtml);
}
File.WriteAllText(filePath, template.Replace("{{content_block}}", dataBuilder.ToString()));
Console.WriteLine("資料已成功寫入檔案。");
}
catch (Exception ex)
{
Console.WriteLine($"Error: {ex.Message}");
}
}
Console.ReadLine();
}
}
}
Element.cs
namespace JsonParsingExample
{
public class PeriodicTable
{
public Element[] Elements { get; set; }
}
public class Element
{
public string Name { get; set; }
public string Appearance { get; set; }
public float Atomic_mass { get; set; }
public float? Boil { get; set; }
public string Category { get; set; }
public float? Density { get; set; }
public string Discovered_by { get; set; }
public float? Melt { get; set; }
public float? Molar_heat { get; set; }
public string Named_by { get; set; }
public int Number { get; set; }
public int Period { get; set; }
public int Group { get; set; }
public string Phase { get; set; }
public string Source { get; set; }
public string Bohr_model_image { get; set; }
public string Bohr_model_3d { get; set; }
public string Spectral_img { get; set; }
public string Summary { get; set; }
public string Symbol { get; set; }
public int Xpos { get; set; }
public int Ypos { get; set; }
public int Wxpos { get; set; }
public int Wypos { get; set; }
public int[] Shells { get; set; }
public string Electron_configuration { get; set; }
public string Electron_configuration_semantic { get; set; }
public float? Electron_affinity { get; set; }
public float? Electronegativity_pauling { get; set; }
public float?[] Ionization_energies { get; set; }
public string Cpkhex { get; set; }
public Image Image { get; set; }
public string Block { get; set; }
}
public class Image
{
public string Title { get; set; }
public string Url { get; set; }
public string Attribution { get; set; }
}
}
template.html
<!DOCTYPE html>
<html>
<head>
<title>Bootstrap Layout</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css">
</head>
<body>
<div class="container">
<h1>Elements</h1>
<div class="row">
{{content_block}}
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>