How to Fix Hugo JSON-LD Escaping Problem

Some string values on JSON-LD are escaped when generated using the latest Hugo

I’ve been using Hugo static site generator for a long time. It’s from version 0.34 if I remember correctly. I’ve been using that version for a year and so far it works just fine. I build my theme based on that version too. And it’s been forever I keep the theme code as it is because I thought that’s good enough.

Recently I decided to give the update for Hugo version 0.68.3. The purpose is just to want to catch up with the latest version.

To my surprise, there are some wrong results when I use the same theme. I was alerted by the Google Webmaster tool that my pages contain wrong unparsable JSON-LD structured data.

The first thing I notice how Hugo change the output of the date. I remember by default it will print the date with ISO 8601 standard. This standard has + or - character based on the time zone.

Since I live in the west part of Indonesia, I expect the date ended with +07:00. But to my surprise, Hugo replaces + with \x2b. Who am I kidding, the date format is not ISO 8601 anymore.

Not just that, Hugo even escapes all of the URLs I put there.

For your illustration, take a look at the following snippet. This is the original Hugo template script I have to generate some dates and URLs.

{
    "datePublished": "{{ .Date }}",
    "dateModified" : "{{ .Lastmod | default .Date }}",
    "url" : "{{ .Permalink }}",
}

When I use the template above, I get results like the following snippet. This is the wrong result.

{
    "datePublished": "2020-04-01 15:03:56 \x2b0700 WIB",
    "dateModified" : "2020-04-01 15:22:32 \x2b0700 WIB",
    "url" : "https:\/\/www.godo.dev\/",
}

My expected result would be like the following snippet. This is the correct result.

{
    "datePublished": "2018-08-07T10:12:10+07:00",
    "dateModified" : "2020-04-02T07:22:04+07:00",
    "url" : "https://www.godo.dev/",
}

Somehow, the solution also surprisingly weird. For the date value, if you want to get an ISO 8601 format, you have to do that manually. Then, if you don’t want Hugo to escape the date or URL string, just write it without quotes. Yes, you read that right. You need to remove the quotes.

Here is the example solution I use.

{{ $ISO8601 := "2006-01-02T15:04:05-07:00" }}
{
    "datePublished": {{ (.Date.Format $ISO8601) }},
    "dateModified" : {{ (.Lastmod.Format $ISO8601) | default (.Date.Format $ISO8601) }},
    "url" : {{ .Permalink }},
}

By using the above snippet, I get the value as expected.

Hopefully, Hugo reaches v1.0 soon. I just hope to not face another breaking result when I update Hugo to the latest version.

But, Hugo still is my favorite static site generator. Because it’s so fast!

Thank you for reading. Hope this simple tutorial helps you.

References