C#/.NET 序列化和反序列化 YAML 元數據

原文鏈接:https://blog.walterlv.com/post/serialize-and-deserialize-yaml.html

項目中需要將Yaml文件反序列化爲自定義的強類型對象進而對其內容進行修改。

這裏參考https://blog.walterlv.com/post/serialize-and-deserialize-yaml.html

.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);
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章