解决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即可。
  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值