transform.Unmarshal

輸入內容可以是字串或資源

解析字串

{{ $string := `
title: 悲慘世界
author: 維克多·雨果
`}}

{{ $book := unmarshal $string }}
{{ $book.title }} → 悲慘世界  
{{ $book.author }} → 維克多·雨果  

解析資源

使用 transform.Unmarshal 函數解析全域、頁面或遠端資源。

全域資源

全域資源是位於 assets 目錄中的檔案,或掛載至該目錄的檔案。

assets/
└── data/
    └── books.json
{{ $data := dict }}
{{ $path := "data/books.json" }}
{{ with resources.Get $path }}
  {{ with . | transform.Unmarshal }}
    {{ $data = . }}
  {{ end }}
{{ else }}
  {{ errorf "無法取得全域資源 %q" $path }}
{{ end }}

{{ range where $data "author" "Victor Hugo" }}
  {{ .title }} → 悲慘世界
{{ end }}

頁面資源

頁面資源是位於頁面包中的檔案。

content/
├── post/
│   └── book-reviews/
│       ├── books.json
│       └── index.md
└── _index.md
{{ $data := dict }}
{{ $path := "books.json" }}
{{ with .Resources.Get $path }}
  {{ with . | transform.Unmarshal }}
    {{ $data = . }}
  {{ end }}
{{ else }}
  {{ errorf "無法取得頁面資源 %q" $path }}
{{ end }}

{{ range where $data "author" "Victor Hugo" }}
  {{ .title }} → 悲慘世界
{{ end }}

遠端資源

遠端資源是位於 HTTP 或 HTTPS 伺服器上的檔案。

{{ $data := dict }}
{{ $url := "https://example.org/books.json" }}
{{ with resources.GetRemote $url }}
  {{ with .Err }}
    {{ errorf "%s" . }}
  {{ else }}
    {{ $data = . | transform.Unmarshal }}
  {{ end }}
{{ else }}
  {{ errorf "無法取得遠端資源 %q" $url }}
{{ end }}

{{ range where $data "author" "Victor Hugo" }}
  {{ .title }} → 悲慘世界
{{ end }}

選項

在解析 CSV 檔案時,可以提供一個選項 map。

  • delimiter (string):使用的分隔符,預設為 ,
  • comment (string):CSV 中使用的註解字符。如果設置,則以此字符開頭且無前置空白的行會被忽略。
  • lazyQuotes (bool):若為 true,則允許引號出現在未引用的欄位中,或非雙引號出現在引用的欄位中。預設為 false
{{ $csv := "a;b;c" | transform.Unmarshal (dict "delimiter" ";") }}

處理 XML

在解析 XML 時,存取資料時不包含根節點。例如,解析以下 RSS Feed 後,可以透過 $data.channel.title 存取標題。

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>範例網站的書籍</title>
    <link>https://example.org/books/</link>
    <description>範例網站的書籍中最新內容</description>
    <language>en-US</language>
    <atom:link href="https://example.org/books/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>巴黎聖母院</title>
      <description>作者:維克多·雨果</description>
      <link>https://example.org/books/the-hunchback-of-notre-dame/</link>
      <pubDate>Mon, 09 Oct 2023 09:27:12 -0700</pubDate>
      <guid>https://example.org/books/the-hunchback-of-notre-dame/</guid>
    </item>
    <item>
      <title>悲慘世界</title>
      <description>作者:維克多·雨果</description>
      <link>https://example.org/books/les-miserables/</link>
      <pubDate>Mon, 09 Oct 2023 09:27:11 -0700</pubDate>
      <guid>https://example.org/books/les-miserables/</guid>
    </item>
  </channel>
</rss>

取得遠端資料:

{{ $data := dict }}
{{ $url := "https://example.org/books/index.xml" }}
{{ with resources.GetRemote $url }}
  {{ with .Err }}
    {{ errorf "%s" . }}
  {{ else }}
    {{ $data = . | transform.Unmarshal }}
  {{ end }}
{{ else }}
  {{ errorf "無法取得遠端資源 %q" $url }}
{{ end }}

檢查資料結構:

<pre>{{ debug.Dump $data }}</pre>

列出書籍標題:

{{ with $data.channel.item }}
  <ul>
    {{ range . }}
      <li>{{ .title }}</li>
    {{ end }}
  </ul>
{{ end }}

Hugo 將渲染如下:

<ul>
  <li>巴黎聖母院</li>
  <li>悲慘世界</li>
</ul>

XML 屬性與命名空間

以下為 RSS Feed 添加 lang 屬性至 title 節點,並新增一個帶有命名空間的 ISBN 節點:

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0"
  xmlns:atom="http://www.w3.org/2005/Atom"
  xmlns:isbn="http://schemas.isbn.org/ns/1999/basic.dtd"
>
  <channel>
    <title>範例網站的書籍</title>
    <link>https://example.org/books/</link>
    <description>範例網站的書籍中最新內容</description>
    <language>en-US</language>
    <atom:link href="https://example.org/books/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title lang="en">巴黎聖母院</title>
      <description>作者:維克多·雨果</description>
      <isbn:number>9780140443530</isbn:number>
      <link>https://example.org/books/the-hunchback-of-notre-dame/</link>
      <pubDate>Mon, 09 Oct 2023 09:27:12 -0700</pubDate>
      <guid>https://example.org/books/the-hunchback-of-notre-dame/</guid>
    </item>
    <item>
      <title lang="fr">悲慘世界</title>
      <description>作者:維克多·雨果</description>
      <isbn:number>9780451419439</isbn:number>
      <link>https://example.org/books/les-miserables/</link>
      <pubDate>Mon, 09 Oct 2023 09:27:11 -0700</pubDate>
      <guid>https://example.org/books/les-miserables/</guid>
    </item>
  </channel>
</rss>

取得遠端資料後,檢查資料結構:

<pre>{{ debug.Dump $data }}</pre>

每個項目節點的結構如下:

{
  "description": "作者:維克多·雨果",
  "guid": "https://example.org/books/the-hunchback-of-notre-dame/",
  "link": "https://example.org/books/the-hunchback-of-notre-dame/",
  "number": "9780140443530",
  "pubDate": "Mon, 09 Oct 2023 09:27:12 -0700",
  "title": {
    "#text": "巴黎聖母院",
    "-lang": "en"
  }
}

由於部分鍵值名稱不是有效的識別符,需要使用 index 函數來存取這些值:

{{ with $data.channel.item }}
  <ul>
    {{ range . }}
      {{ $title := index .title "#text" }}
      {{ $lang := index .title "-lang" }}
      {{ $ISBN := .number }}
      <li>{{ $title }} ({{ $lang }}) {{ $ISBN }}</li>
    {{ end }}
  </ul>
{{ end }}

Hugo 將渲染如下:

<ul>
  <li>巴黎聖母院 (en) 9780140443530</li>
  <li>悲慘世界 (fr) 9780451419439</li>
</ul>