跳到主要内容
  1. Skills/
  2. Hugo 使用指南/

让 hugo 输出 json

··字数 1640·4 分钟
howto

我们使用 hugo 来生成静态网页,大部分情况下,就是让它生成 html 文件。生成的静态网站文件,一般都托管在web 服务,或者目前技术界非常流行的 github pages,netlify。但对于能否用 hugo 来生成其它格式(如 json)的文件,貌似从未思考过。因为 json 文件也可以作为静态文件一同在 web服务托管服务上被访问。如果能使用 hugo 来直接生成 json,那么意味着不需要引入新工具。

今天,有悟尝试一下,看如何使用 hugo 来生成 json 文件。

作为当前最流行的静态网站生成工具之一,当然包含了对输出文件格式的定义功能。 在官方文档中,针对输出格式有一篇说明文章, Custom Output Formats ,看标题,意味着这里存在非常大的配置内容。

该文开头的一句概括性描述,道明了 hugo 提供输出格式定义的所有可能:

Hugo can output content in multiple formats, including calendar events, e-book formats, Google AMP, and JSON search indexes, or any custom text format.

其中,最重要的关键词,any custom text format。因为 hugo 使用了 golang 自带的模板系统,任何可以使用该模板语言定义出来的文本模板,都可用来定制 hugo 的输出格式。

基于此,我们不难理解, hugo 所支持的媒体类型 ,除音频、视频、图片格式(这些格式的文件不是由 hugo 生成的,而是作为静态文件、资源文件类型能被 hugo 识别)外,其它都是可以使用 文本编辑器打开的文件格式 ,这些文本型的媒体类型,是由 文本型文件 + 格式类型声明 组成。并且 hugo 中不仅没有限制自定义媒体格式,反而支持自定义媒体类型。可以先定义新的文本型媒体类型,再声明一个关联了对应媒体类型的新的输出格式,其实就是标明一些名称,这些 hugo 运行时可以使用这个名称来定位模板文件、输出文件的后续名。在上面的官方文档链接中已经有详细说明,这里不重复。


因为 json 是受 hugo 所支持的内置媒体类型,无须重复定义(不需要像官方文档中声明的那样去定义新的媒体类型),只要我们在内容的 front matter 中指定输出格式为 json 即可,hugo 会按照统一的模板 lookup 规则定位到对应 json 模板文件。

以本文为例,我们使用 markdown 来编写内容,默认情况下输出格式为 html。hugo 会按照模板lookup规则,查找后缀为 .html 的模板文件。对应的 front matter 类似于,

title: "让 hugo 输出 json"
slug: "hugo json output"
date: 2021-07-19T17:25:42+08:00
lastmod: 2021-07-19T17:25:42+08:00

然后通过 https://youwu.today/skill/hugo/hugo-json-output/ 访问。

设置输出格式为 json #

如果要让它生成 json格式,那么 front matter 要加上相关内容。

title: "让 hugo 输出 json"
slug: "hugo json output"
...
outputs:
    - json

除非你已经定义了一个默认的 json 模板,不然,hugo 的命令会提示如下异常:

WARN 2021/08/12 23:48:46 found no layout file for "JSON" for kind "page": You should create a template file which matches Hugo Layouts Lookup Rules for this combination.

为 json 格式定制一个模板文件 #

json 模板与 html 模板的查找规则是一样的。我们先来定义一个简单的 json 模板。姑且命名为 hugo-json-output.json 吧,放在可以被文本识别的路径,如 layouts/skill/ 下,为其添加一段符合 json 格式的内容:

{
    "youwu.today": "say hi"
}

这时内容的 front matter 中指定 layout :

title: "让 hugo 输出 json"
slug: "hugo json output"
layout: 'hugo-json-output'
outputs:
    - json

hugo生成网站后,通过地址 https://youwu.today/skill/hugo/hugo-json-output/index.json 就可以访问这个 json 文件了。注意,不是 /skill/hugo/hugo-json-output.json哦。

为了演示需要,这个 json 格式文件被保留,即,你当前可以访问到这个json。这也是本站中少有的存在两个格式的地址。

这时,以 html 方式访问 hugo-json-output 会得到一个空白页,因为 hugo 只生成了 json 格式,原有的 html 格式不再存在。(/skill/hugo/hugo-json-output/ 路径下的 index.html 文件不存在)

同时输出 json、html #

只要在 outputs 中同时指定 jsonhtml,那么 hugo 就会同时生成两种格式的文件。 这时的 front matte 类似于:

title: "让 hugo 输出 json"
slug: "hugo json output"
layout: 'hugo-json-output'
outputs:
    - json
    - html

通过 /skill/hugo/hugo-json-output/index.html/skill/hugo/hugo-json-output/index.json 会分别看到 html页面和 json 数据。

  • json 格式,使用了 layouts/skill/hugo-json-output.json 作为模板
  • html 格式,因为没有找到 hugo-json-output.html 模板文件,根据 hugo lookup 规则,会回退到 skill/single.html 这个模板。

偷偷告诉你,有人发现了这个秘密,通过声明新的媒体类型并绑定 html 格式,使 hugo 可以为一篇内容生成多个 html 页面。

众所周知,hugo 一篇内容文章生成的页面数为 内容*输出格式数,默认配置情况下,一篇内容只为用户生成一个 html 页面。(列表页因为有分页功能,属于例外情况)