C#/.NET 序列化和反序列化 YAML 元數據
發佈於 2018-08-12 12:44 更新於 2018-08-12 21:47
我希望能夠對我博客中的所有 YAML 元數據進行格式化和自動生成,於是我需要進行一些 YAML 解析和寫入的操作。
.NET 並沒有原生提供對 YAML 的序列化和反序列化。雖然 YAML 文件的解析並不難,不過如果不是處於特別的理由(比如性能),使用現有的庫解析 YAML 是比較好的選擇。
本文推薦使用 YamlDotNet 序列化和反序列化 YAML。
YAML 元數據
作爲示例,我拿出我在去年寫的一篇博客的元數據進行分析:
layout: post title: "利用 TypeConverter,轉換字符串和各種類型只需寫一個函數" date_published: 2017-01-17 18:13:00 +0800 date: 2018-04-23 07:31:32 +0800 categories: dotnet permalink: /dotnet/2017/01/17/convert-using-type-converter.html keywords: dotnet typeconverter description: 使用 TypeConverter 實現字符串轉各種類型。
注意,實際上元數據是包含開始標籤和結束標籤的。yaml 元數據以 ---
包裹,toml 元數據以 +++
包裹。
由於從 Markdown 中解析出 YAML 元數據不是本文的重點,所以我放到最後一起說明。
定義 .NET 類型
我們需要先定義 .NET 類型,以便 YamlDotNet 進行序列化和反序列化。
public sealed class YamlFrontMeta { [YamlMember(Alias = "title", ApplyNamingConventions = false)] public string Title { get; set; } [YamlMember(Alias = "date", ApplyNamingConventions = false)] public string Date { get; set; } [YamlMember(Alias = "date_published", ApplyNamingConventions = false)] public string PublishDate { get; set; } [YamlMember(Alias = "layout", ApplyNamingConventions = false)] public string Layout { get; set; } [YamlMember(Alias = "permalink", ApplyNamingConventions = false)] public string PermanentUrl { get; set; } [YamlMember(Alias = "categories", ApplyNamingConventions = false)] public string Categories { get; set; } [YamlMember(Alias = "tags", ApplyNamingConventions = false)] public string Tags { get; set; } [YamlMember(Alias = "keywords", ApplyNamingConventions = false)] public string Keywords { get; set; } [YamlMember(Alias = "description", ApplyNamingConventions = false)] public string Description { get; set; } [YamlMember(Alias = "versions", ApplyNamingConventions = false)] public List<VersionsInfo> Versions { get; set; } [YamlMember(Alias = "published", ApplyNamingConventions = false)] public bool IsPublished { get; set; } = true; [YamlMember(Alias = "sitemap", ApplyNamingConventions = false)] public bool IsInSiteMap { get; set; } = true; }
.NET 類型中的屬性必須是 YAML 文件中屬性的超集。
以上 ApplyNamingConventions
屬性的默認值是 true
,這爲了解決一些命名約束上的問題,詳見:YamlMember Alias isn’t applied when using the CamelCaseNamingConvention · Issue #228 · aaubry/YamlDotNet。
另外,如果 YAML 屬性中包含數組,則需要將屬性的類型設置爲集合類型。
title: "Good Framework Rely on Good Api —— Six API Design Principles" date_published: 2018-06-30 19:09:53 +0800 date: 2018-08-12 16:04:26 +0800 categories: dotnet framework versions: - 中文: /post/framework-api-design.html - English: #
public sealed class VersionInfo { [YamlMember(Alias = "current", ApplyNamingConventions = false)] public string Current { get; set; } } public sealed class VersionsInfo { [YamlMember(Alias = "中文", ApplyNamingConventions = false)] public string Chinese { get; set; } [YamlMember(Alias = "English", ApplyNamingConventions = false)] public string English { get; set; } }
序列化與反序列化
使用 Deserializer
類型可以反序列化一個 YAML 元數據。
var deserializer = new Deserializer(); var matter = deserializer.Deserialize<YamlFrontMeta>(yamlText);
使用 Serializer
類型可以序列化一個 YAML 元數據到字符串。這樣,就能更新博客的 YAML 元數據部分了。
var serializer = new Serializer(); var yamlText = serializer.Serialize(matter);
本文會經常更新,請閱讀原文: https://walterlv.com/post/serialize-and-deserialize-yaml.html ,以避免陳舊錯誤知識的誤導,同時有更好的閱讀體驗。
本作品採用 知識共享署名-非商業性使用-相同方式共享 4.0 國際許可協議 進行許可。歡迎轉載、使用、重新發布,但務必保留文章署名 呂毅 (包含鏈接: https://walterlv.com ),不得用於商業目的,基於本文修改後的作品務必以相同的許可發佈。如有任何疑問,請 與我聯繫 ([email protected]) 。