解決golang中json.Marshal方法html字符轉義

  1. 起因
    今天在接微信小程序碼生成接口的時候發現報invalid scene hint的錯誤,debug後發現是因爲我scene參數中的html字符被轉義而導致的,原始提交的參數爲qrt=cp&qrk=lottery,但是api提交的參數爲qrt=cp\u0026qrk=lottery如下圖所示:
    debug圖

  2. 分析
    debug後發現,是因爲經過了json.Marshal方法後,html的字符才被轉義的。
    查看json.Marshal源碼

func Marshal(v interface{}) ([]byte, error) {
	e := newEncodeState()

	err := e.marshal(v, encOpts{escapeHTML: true})
	if err != nil {
		return nil, err
	}
	buf := append([]byte(nil), e.Bytes()...)

	e.Reset()
	encodeStatePool.Put(e)

	return buf, nil
}

源碼中就看到了其中的“貓膩”—>>escapeHTML:true,再看看方法的註釋說明,以下是其中一段說明

// String values encode as JSON strings coerced to valid UTF-8,
// replacing invalid bytes with the Unicode replacement rune.
// The angle brackets "<" and ">" are escaped to "\u003c" and "\u003e"
// to keep some browsers from misinterpreting JSON output as HTML.
// Ampersand "&" is also escaped to "\u0026" for the same reason.
// This escaping can be disabled using an Encoder that had SetEscapeHTML(false)
// called on it.

簡單的說就是,字符串在編碼爲JSON字符串時會被強制轉換爲有效的UTF-8,爲了防止一些瀏覽器在JSON輸出誤解以爲是HTML,“<”,“>”,“&”這類字符會被進行轉義,如果不想被轉義,就使用Encoder,並且SetEscapeHTML(false)即可

  1. 驗證
    使用json.Marshal生成json字符串
func main() {
	testMap := map[string]string{
		"demo": `https://xxx.xxx.com?a=1&b=2`,
	}
	bytes, err := json.Marshal(testMap)
	if err != nil {
		panic(err)
	}
	fmt.Println(string(bytes))
}
輸出結果:{"demo":"https://xxx.xxx.com?a=1\u0026b=2"}
可見,& 符號已經被轉義

使用Encoder生成字符串

func main() {
	testMap := map[string]string{
		"demo": `https://xxx.xxx.com?a=1&b=2`,
	}
	byteBuf := bytes.NewBuffer([]byte{})
	encoder := json.NewEncoder(byteBuf)
	encoder.SetEscapeHTML(false)
	err := encoder.Encode(testMap)
	if err != nil {
		panic(err)
	}
	fmt.Println(byteBuf.String())
}
輸出結果:{"demo":"https://xxx.xxx.com?a=1&b=2"}
可見,& 符號沒有被轉義
  1. 總結
    golang中,在對象轉成json字符串的時候,如果不希望字符串中含有的html特殊字符被轉義,可以使用Encoder對象並且SetEscapeHTML(false)即可。如果沒有這種需求則使用json.Marshal即可。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章