问题
json.Marshal()
函数在处理html标签字符中,会存在转义问题。Marshal方法默认把html标签中的'<', '>' , '&'字符转义成unicode,为强制为有效UTF-8的JSON字符串,用Unicode替换符号替换无效字节。
所以当时在网上找了 这篇文章:golang——json的html转义问题
虽然他提供了解决方案 解决了字符串转义的问题,但是却带来了新的问题
type Message struct {
Content string
}
func main() {
content := `content`
m := Message{content}
res1, _ := json.Marshal(&m)
res2, _ := JsonMarshalNoSetEscapeHTML(&m)
fmt.Println(len([]byte(res1)), len(res2))
fmt.Println(string(res1) == string(res2))
}
func JsonMarshalNoSetEscapeHTML(data interface{}) ([]byte, error) {
bf := bytes.NewBuffer([]byte{})
jsonEncoder := json.NewEncoder(bf)
jsonEncoder.SetEscapeHTML(false)
if err := jsonEncoder.Encode(data); err != nil {
return nil, err
}
return bf.Bytes(), nil
}
输出
21 22
false
我们期望对于普通字符串,序列化出来的字节数相同 以及 字符串比较是相等的,但是实际上并没有
原因
由于字符串不长,我们可以直接把字节数组打印出来
[123 34 67 111 110 116 101 110 116 34 58 34 99 111 110 116 101 110 116 34 125]
[123 34 67 111 110 116 101 110 116 34 58 34 99 111 110 116 101 110 116 34 125 10]
我们可以看到是 res2 比 res1 多了一个 10
。通过查看 ascii 码表,可以发现 10
表示的是 LF
也就是换行
我们再看 Encode
函数的源码
// Terminate each value with a newline.
// This makes the output look a little nicer
// when debugging, and some kind of space
// is required if the encoded value was a number,
// so that the reader knows there aren't more
// digits coming.
e.WriteByte('\n')
翻译一下:“用一个换行来结束每个值。这使得在调试时输出看起来更漂亮,如果编码的值是一个数字,则需要一些空格,这样读者就知道不会有更多的数字出现。”
总结
有时候需要对序列化出来的字符串校验md5值,如果多了一个空格 则 md5 校验会不通过。这是一个坑。至于如何解决,最简单的办法就是,返回的时候去掉多加的换行。或者在需要操作的时候再去掉
b := bf.Bytes()
return b[:len(b)-1], nil