-
起因
今天在接微信小程序碼生成接口的時候發現報invalid scene hint
的錯誤,debug後發現是因爲我scene參數中的html字符被轉義而導致的,原始提交的參數爲qrt=cp&qrk=lottery
,但是api提交的參數爲qrt=cp\u0026qrk=lottery
如下圖所示:
-
分析
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)即可。
- 驗證
使用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"}
可見,& 符號沒有被轉義
- 總結
golang中,在對象轉成json字符串的時候,如果不希望字符串中含有的html特殊字符被轉義,可以使用Encoder對象並且SetEscapeHTML(false)即可。如果沒有這種需求則使用json.Marshal即可。