前言

問題

專案中使用 golang + gin 開發網站,並且有使用 JSON-LD,然而 JSON-LD 中的「&」字符卻預期外的被替換成了「\x26」。


問題程式碼

發生問題的程式碼如下。

相關問題

經過一番搜尋,發現 Golang「Hugo」框架也有一樣的問題,Hugo 可以透過 {{ printf "\"%s\"" .Title | safeJS }} 解決。有興趣的朋友可以參考下方連結。

Problems with encoding special characters in json+ld (“invalid escape sequence”)

追查問題所在

gin 使用 (gin.Context) HTML 方法渲染網頁,而深入追查至最後,可以發現 gin 是使用 html/template 進行渲染。

因此我們經由下方程式碼追查 html/template 後,發現問題不單純是 gin 框架造成,

而是 html/template 原本就有這樣的問題,而 gin 使用了 html/template 進行渲染。

使用 html/template 重現問題

追蹤 Hugo解決方案

深入追查後,發現 Hugo 的「safeJS」解決方案是框架中加入的 template FuncMap,

為此我們撰寫了下列程式測試,並且確實成功打印了「&」符號。

我們可以從程式碼中看到,其實「safeJS」只是 Hugo 框架利用 cast 將輸入值轉為字串,最終輸出為 template.JS,並且上述的解決方案還還有一個步驟,就是將雙引號一起透過 template.JS 轉換後打印,若我們將 cast 拿掉,程式如下

請注意,這邊一定要使用 printf,再將加上雙引號的參數給 safeJS 處理。

否則,若是將參數進行 safeJS 處理,又在參數外加上雙引號渲染,還是會被編碼。

結論

這邊我們得到一個結論:

html/template 在打印時,會被編碼


ex:

"description": "{{.testTextWithAnd}}" ===> "description": "a \x26 b"


ex:

"description": {{.testTextWithAnd}} ===> "description": "a \u0026 b"

解決方案

我們如果將要打印到 script 中的參數,先透過 template function,使用 template.JS (html/template)方法,返回參數後打印,就可以解決被編碼的問題。

若使用 text/template 則不會有此問題

FBLINETwitterLinkIn
回部落格